I have three div 1, 2 and 3 within a main div i.e:
<div id="main">
<div style="height:30px; background-color:yellow;" class="bnr">Banner</div>
<div style="height:30px; background-color:yellow;" class="bnr">Banner2</div>
<div style="height:30px; background-color:yellow;" class="bnr">Banner3</div>
</div>
Now, I want to append a dragged <div class="other"></div> after any of a <div> with class 'bnr', append then, when I drop on 'placeholder'. i.e when I mouse over on any of these three <div>, it shows a 'placeholder' in between. like I am mouse hovering on <div> 1 and it will show a placeholder <div> in between <div> 1 and <div> 2.
Placeholder is like:
<div style="height:30px; background-color:light-yellow;" class="placeholder"></div>
I have concluded with my try that I have to use '.droppable' function property 'over', 'out' and 'drop', instead of using, jquery's .mouseenter and .mouseleave functions.
$(".other").draggable({
helper: 'clone'
});
$('.placeholder').droppable({
over: function (event, ui) {
},
out: function (event, ui) {
},
drop: function (event, ui) {
}
});
How can I drop on 'placeholder' div?
Because its created after mouseover. So from here '.on' function comes into play. Now tell me how I can use '.droppable' with '.on' or help me to find any other solution.
here is a sample code:
$(".other").draggable({
helper: 'clone'
});
$('.bnr').droppable({
over: function (event, ui) {
$('.placeholder').remove();
$('<div style="height:30px; background-color:light-yellow;" class="placeholder"></div>').insertAfter(this);
},
out: function (event, ui) {
},
drop: function (event, ui) {
$('.placeholder').remove();
$(".other").insertAfter(this);
}
});
see working demo: http://jsbin.com/hoyonugupu/edit?html,js,output
It looks like you're looking for a draggable which is connected to sortable widget having custom placeholder via connectToSortable option:
$('#main').sortable({
placeholder: 'placeholder'
});
$('.draggable').draggable({
helper: 'clone',
connectToSortable: '#main'
});
#main {
margin-bottom: 50px;
}
#main div.bnr {
height: 30px;
background-color: yellow;
}
.placeholder {
visibility: visible;
height: 30px;
background-color: orange;
}
.draggable {
width:100%;
height: 30px;
background: dodgerblue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
<div id="main">
<div class="bnr">Banner</div>
<div class="bnr">Banner2</div>
<div class="bnr">Banner3</div>
</div>
<div class="draggable">Drag Me</div>
No need to manually inject elements and stuff, jQuery UI has inbuilt options for these interactions.
Side note: Please don't use inline styles.
Related
I'm asking as a last resort before I tear the last of my hair out. At the moment I am showing an initial 2 divs. The user can then add these two divs below the original as many times as they want. They can also remove the 2 divs if necessary. I am trying to allow reording of the divs using drage and drop. I've tried numerous methods but I just can't get it working. As an extra note, the divs need to reindex themselves once the user has dragged and dropped. Here is the code that I have. Please take into consideration that I have added and deleted lots of code attempts before settling on this basic implementation. Thanks in advance.
Load JQuery
Display first div to end user
<!--Div contains each answer step-->
<div id = "answer_step" class = "answer_step">
<!--This placeholder text is styled from CSS and will empty the div once the user starts typing-->
<div id="answer_step_equation0" class="answer_step_equation" contenteditable="true" placeholder="Enter The Next Solution Step This Question"></div>
<div id="answer_step_description0" class = "answer_step_description" contenteditable="true" placeholder="Enter A Description as to how this step was reached or how to solve the next step"></div>
</div>
</div>
<!-- Buttons to dynamically add and remove answer divs. The remove functionality is added in JQuery for the add button-->
<button id="add_answer_step_button" class="add_answer_step_button">+ Add next Step</button>
This code appends the new divs. I have to put the three divs within a div like above but I can't get it to work.
<!--Script to append/remove div when user clicks on add_answer_step_button-->
<script type = "text/javascript" language = "javascript">
$(document).ready(function() {
<!--This variable gives each new set of answer divs a unique id by appending a number to the end of th id-->
<!--The first set of answer divs will have an id of zero-->
var answer_identifier_number = 1;
$("button.add_answer_step_button").click(function () {
$("div.answer_steps").append('<div id="answer_step_equation' + answer_identifier_number + '" class="answer_step_equation" contenteditable="true" placeholder="Enter The Next Solution Step This Question"></div>');
$("div.answer_steps").append('<div id="answer_step_description' + answer_identifier_number + '" class = "answer_step_description" contenteditable="true" placeholder="Enter A Description as to how this step was reached or how to solve the next step"></div>');
$("div.answer_steps").append('<button id="remove_answer_step_button' + answer_identifier_number + '" class = "remove_answer_step_button">- Remove This Step</button>');
answer_identifier_number++;
});
});
</script>
Allow the divs to be draggable
<script type = "text/javascript" language = "javascript">
$(function() {
$( "#answer_steps" ).sortable();
$( "#answer_steps" ).disableSelection();
cursor: move;
});
</script>
I haven't figured out how to reindex the names yet but I have experience of that part so I should be fine. Thanks for your help.
ok, before you go tearing your hair out, have a look at this 'drag and drop' fiddle - its a heres-one-I made-earlier one jsfiddle.net/RachGal/ahnx7kwc It'll give you an idea about how the whole drag and drop thing works – Rachel Gallen 2 days ago
The HTML from this fiddle
<div class="common">
<div class="container-fluid">
<div class="row">
<ul class="col-sm-3 col-md-2 sidebar nav nav-sidebar" >
<li class="group" class="draggable" ><a href="#" class="list-group-item">
<h4>
dsad
<br /><small>dsadsa</small>
<br /><small>dsadsa</small>
</h4>
</a>
</li>
<li class="group" class="draggable"><h2>
BAH
</h2><br><small>hello</small>
</ul>
<div id="drophere" class="col-sm-9 col-md-9">MAIN PANEL</div>
</div>
</div>
The Javascript from this fiddle
$(".draggable").draggable();
var draggableArguments={
revert: 'invalid',
helper:'clone',
appendTo: '#drophere',
refreshPositions: true,
containment: 'DOM',
zIndex: 1500,
addClasses: false
};
$('.group').draggable(draggableArguments);
$('.group').droppable();
$(".nav-sidebar").droppable({
tolerance: "intersect",
accept: ".group",
activeClass: "ui-state-default",
hoverClass: "ui-state-hover",
drop: function(event, ui) {
$(".nav-sidebar").append($(ui.draggable));
}
});
$('#drophere').droppable({
tolerance: "intersect",
accept: ".group",
activeClass: "ui-state-default",
hoverClass: "ui-state-hover",
drop: function(event, ui) {
$('#drophere').append($(ui.draggable));
}
});
$('#drophere').sortable();
The CSS from this Fiddle
.draggable {
border: solid 2px gray;
}
.sidebar {
position:fixed;
width:200px;
top: 51px;
bottom: 0;
left: 0;
z-index: 1000;
display: block;
padding: 20px;
overflow-y: auto;
/* Scrollable contents if viewport is shorter than content. */
overflow-x: visible;
background-color: #f5f5f5;
white-space: nowrap;
border-right: 1px solid #eee;
padding-left: 30px;
padding-right: 30px;
}
/* Sidebar navigation */
.nav-sidebar {
width:200px;
height:100vh;
margin-right: -21px;
/* 20px padding + 1px border */
margin-bottom: 20px;
margin-left: -20px;
}
.group{width:150px;
height:auto;
}
#drophere{width:700px;left:200px; height:100vh;}
Hopefully this makes sense. I'm creating a drag and drop modal with jquery UI. I have my code set up to fire a function that adjusts some styling using the "over" option. Here's my code.
function makeDraggable(){
$(function(){
$( "tr[role='row']" ).draggable({
cursor: "none",
cursorAt: { top: 50, left: 50 },
containment: "body",
scroll: false,
delay: 200,
start: function() {
openModal();
},
stop: function() {
closeModal();
},
helper: function( event ) {
return $( "<div class='drag-folder'><img src=<?php echo site_url("imgs/processIcons/file_icon.svg");?>></div>" );
}
})
});
makeDroppable();
}
function makeDroppable(){
$(function(){
$( ".flex-item" ).droppable({
tolerance: 'pointer',
over: function(event, ui) {
$(this).find('.drag-container').css('height', (180 + (event.pageY / 5 )));
},
out: function(event, ui) {
$(this).find('.drag-container').css('height', '');
},
drop: function(event, ui) {
$('.drag-container').css('height', '');
}
})
});
}
function openModal(){
var modal = $('.drag-modal');
modal.fadeIn();
}
function closeModal(){
var modal = $('.drag-modal');
modal.fadeOut();
}
The effect I'm trying to achieve is this: The user starts dragging on an element, a modal pops up with several different drop regions. For aesthetic purposes, the height of each drop region stretches vertically towards the mouse. The problem is the height is adjusted using the 'over' option but it only fires once (When the mouse enters the element). Is there some way I can run my code that changes the height every time the mouse moves, but only while over the element?
--edit--
It occurred to me that perhaps this could be achieved using some kind of while loop, but I haven't been able to figure out a solution that doesn't crash the page.
Could you use the ondragover event?
DEMO
JS
function allowDrop(ev) {
document.getElementById("div1").textContent += " dragging! \n";
ev.preventDefault();
}
function drag(ev) {
ev.dataTransfer.setData("text", ev.target.id);
}
function drop(ev) {
ev.preventDefault();
var data = ev.dataTransfer.getData("text");
ev.target.appendChild(document.getElementById(data));
}
HTML
<div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)">
</div>
<img id="drag1" src="https://placeholdit.imgix.net/~text?txtsize=33&txt=350%C3%97150&w=336&h=69" draggable="true" ondragstart="drag(event)" width="336" height="69">
CSS
#div1 {
width: 350px;
height: 70px;
padding: 10px;
border: 1px solid #aaaaaa;
font-size: 5px;
}
I want to create a simple "let's build a look" tool which basically allows a user to drag a div (with an image inside) on to a target area, resize it, rotate it or delete it and do the same with several other elements.
I can create the drag part to all elements and also resize one element but can't do it do more than one.
Here's what I have (I have copied partially the code from an example found here in Stackoverflow):
$(document).ready(function() {
//Counter
counts = [0];
$(".closeMe").hide();
$(".dragImg").draggable({
revert: "invalid",
containment: "#droppable",
helper: "clone",
cursor: "move",
start: function(event, ui) {
counts[0]++;
isDraggingMedia = true;
},
stop: function(event, ui) {
isDraggingMedia = false;
}
});
$("#droppable").droppable({
accept: ".dragImg",
drop: function(e, ui){
if(ui.draggable.hasClass("dragImg"))
$(this).append($(ui.helper).clone());
//Pointing to the dragImg class in dropHere and add new class.
$("#droppable .dragImg").addClass("item-"+counts[0]);
//Remove the current class (ui-draggable and dragImg)
$("#droppable .item-"+counts[0]).removeClass("dragImg ui-draggable ui-draggable-dragging");
$("#droppable .item-"+counts[0]+" .closeMe").addClass("del-"+counts[0]);
$(".item-"+counts[0]).click(function(){
$(".item-"+counts[0]+" .closeMe").show();
//$(".item-"+counts[0]).attr('class', 'ui-draggable-helper');
$(".item-"+counts[0]+" img").resizable({
aspectRatio: true
});
});
make_draggable($(".item-"+counts[0]));
}
});
var zIndex = 0;
function make_draggable(elements){
elements.draggable({
containment:'#droppable',
start:function(e,ui){ ui.helper.css('z-index',++zIndex); },
stop:function(e,ui){}
});
}
});
What I can not do is to achieve resize to every element or even have found a decent way to rotate them or delete them.
I want to click to select and show handles that allow resize, rotate and select and also when clicking outside the element, the handles should disappear.
How can i do this ?
It's a bit hard to answer the question accurately since the HTML is not provided, but I created a tiny sample page implementing these functionalities (dragging, dropping, deleting and resizing). Deleting uses the droppable 'trash' div, you may want to implement the delete functionality within the element similar to drag and resize.
Since jQuery UI provides no rotating functionality in itself, I left that one out. There is several plugins offering this kind of functionality so you should decide which suits you best. Rotating is also offere in CSS3, but you should keep in mind that this approach is very likely to have some browser compatibility issues, for more information see http://caniuse.com/transforms2d.
EDIT: Added a link to a very minimalistic demo application with this functionality: https://github.com/relicode/dragdrop-minimalistic/
<!doctype html>
<head>
<meta charset='utf-8'>
<title>jQuery draggable / droppable test</title>
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.4/themes/smoothness/jquery-ui.css" />
<style>
.drop-hover {
border: solid green 3px;
}
.handle {
display: none;
}
.move-handle {
cursor: move;
}
.rotate-handle {
cursor: pointer;
}
.resize-handle {
cursor: nwse-resize;
}
.trash {
background-color: silver;
display: table-cell;
height: 100px;
vertical-align: middle;
width: 100px;
}
div.area {
border: solid black 1px;
float: left;
height: 500px;
width: 300px;
}
div.interactable {
background-color: silver;
height: 100px;
position: relative;
width: 100px;
}
div.interactable-tools {
bottom: 0;
position: absolute;
width: 100%;
}
p {
text-align: center;
}
</style>
</head>
<body>
<div id='target-area' class='area'>
<p>target</p>
<div class='trash' id='trash'>Trash</div>
</div>
<div id='source-area' class='area'>
<p>source</p>
<div class='interactable'>
Draggable 1
<div class='interactable-tools'>
<span class='handle move-handle'>Mo</span>
<span class='handle rotate-handle'>Ro</span>
<!-- <span class='handle resize-handle'>Re</span> -->
</div>
</div>
<div class='interactable'>
Draggable 2
<div class='interactable-tools'>
<span class='handle move-handle'>Mo</span>
<span class='handle rotate-handle'>Ro</span>
<!-- <span class='handle resize-handle'>Re</span> -->
</div>
</div>
<div class='interactable'>
Draggable 3
<div class='interactable-tools'>
<span class='handle move-handle'>Mo</span>
<span class='handle rotate-handle'>Ro</span>
<!-- <span class='handle resize-handle'>Re</span> -->
</div>
</div>
</div>
<script src='http://code.jquery.com/jquery-1.11.0.min.js'></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.4/jquery-ui.min.js"></script>
<script>
$(document).ready(function() {
var counts = 0; // make sure you use var before your variable name to prevent declaring it as a global variable
$('.interactable')
.resizable()
.draggable({
handle: '.move-handle'
})
.hover(function() {
$(this).find('.handle').toggle();
}, function() {
$(this).find('.handle').toggle();
});
;
$('#target-area').droppable({
drop: function(ev) {
counts += 1;
}
});
$('#trash').droppable({
accept: '.interactable',
drop: function(ev) {
$(ev.toElement).parent().parent().remove();
},
hoverClass: 'drop-hover'
});
});
</script>
</body>
Example:
<div>
<div class='drop'>
<div class='drag'></div>
</div>
<div class='drop'>
</div>
<div class='drop'>
</div>
<div class='drop'>
</div>
<div>
</div>
</div>
$('div.drag').draggable({ containment: 'div.drop' });
Normally, if there is only 1 "div.drop" element, it works as intended. If there are more than 1(like in the example above), I thought that it would be dragged/dropped in any of the "div.drop" divs. As it turns out, it is only draggable/droppable to the first element matched by the "div.drop" selector.
Is there a workaround for this(that is, make it contained/droppable/draggable only in the "div.drop" divs)?
EDIT: I guess you are right guys. After some introspection, I realized that I didn't go for your suggested solutions since there are padding between the divs and I don't want the the "div.drag" divs to be dropped on the padded area.
It don't works like that !!
The containment is to constraint bound of dragging.
You want drag and drop.
Then you have to configure drag for div.grag:
$('div.drag').draggable();
And configure drop for div.drop:
$('div.drop').droppable();
You can add containment for your drag element with your first div level:
<div id='dragZone'>
<div class='drop'>
<div class='drag'></div>
</div>
<div class='drop'>
</div>
</div>
$('div.drag').draggable({ containment: '#dragZone'});
containment restricts the movement of a draggable within the bounds of the given element(s). You could set containment to the parent of the div.drops.
You should make the div.drops droppable, append the draggable on drop, and use the revert: 'invalid' option so that the draggable reverts if it's not dropped on a droppable
$('div.drop').droppable({drop: function(e, ui) {
ui.draggable.appendTo(this);
}});
$('div.drag').draggable({
helper: 'clone',
revert: 'invalid'
});
As the guys have pointed out the containment selector does not work like that as it Constrains dragging to within the bounds of the specified element or region.
You could try something like below:
JQuery References:
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.0/jquery.min.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.9/jquery-ui.min.js"></script>
HTML:
<div id="dragContainer">
<div class='drop'>
<div class='drag'>drag</div>
</div>
<div class='drop'>drop
</div>
<div class='drop'>drop
</div>
<div class='drop'>drop
</div>
<div class='nodrop'>
</div>
</div>
JQuery:
<script type="text/javascript">
$('div.drag').draggable({ containment: '#dragContainer', revert: "invalid" });
$('div.drop').droppable( {
drop: handleDropEvent
} );
function handleDropEvent( event, ui ) {
var draggable = ui.draggable;
alert( 'Ok to drop here onto me!' );
}
</script>
Do try my code
<style>
.container {
border: 2px solid #000;
}
.container img {
width: 45px;
height: 45px;
}
.draggable {
width: 40px;
height: 40px;
background: #F90;
border-radius: 10px;
margin: 0 0 0 0;
float: top;
}
.draggable.is-pointer-down {
background: #09F;
z-index: 2; /* above other draggies */
}
.draggable.is-dragging { opacity: 0.7; }
</style>
<script>
$(document).ready( function() {
var $draggables = $('.draggable').draggabilly({
// contain to parent element
**containment: "#box"**
});
});
</script>
Hello. I think this might help you :)
<div class="container" id="box">
and my images are inside this div.
I have an interesting question. Theoretically, let's say you have a navigation bar on the left with a series of shapes: a circle, square and triangle and to the right of the nav bar you have a blank canvas.
Using Jquery UI or Jquery Mobile, would it be possible to be able to drag shapes from the navigation bar onto the canvas, but for the original shape to still remain in the bar?
Many thanks,
LS
See http://jqueryui.com/demos/droppable/#photo-manager for an example -- the trick is to clone the original element using something like $( ".selector" ).draggable( "option", "helper", 'clone' );
Here is Running Example for intended task -
$(function () {
$("#draggable").draggable({
helper: "clone",
cursor: 'move'
});
$("#container").droppable({
drop: function (event, ui) {
var $canvas = $(this);
if (!ui.draggable.hasClass('canvas-element')) {
var $canvasElement = ui.draggable.clone();
$canvasElement.addClass('canvas-element');
$canvasElement.draggable({
containment: '#container'
});
$canvas.append($canvasElement);
$canvasElement.css({
left: (ui.position.left),
top: (ui.position.top),
position: 'absolute'
});
}
}
});
});
#draggable {
width: 20px;
height: 20px;
background:blue;
display:block;
float:left;
border:0px
}
#container {
width:200px;
height:200px;
background:yellow;
margin:25px;
<script src="http://code.jquery.com/ui/1.10.2/jquery-ui.js"></script>
<div id="draggable" class="ui-widget-content">
<div id="draggable" class="ui-widget-content"></div>
</div>
<div id="container" class="ui-widget-content">Drop blue box here..</div>
Link To JS Fiddle
http://jsfiddle.net/4VRUK/
improve it further as you want.
Add the helper: clone option.
Add helper: clone to the options. If you want the original object to remain be visible, you must set this explicitly:
$(".sortable").sortable({
helper: 'clone',
start: function(event, ui) {
$(ui.item).show()
}