I'm sorry for my bad English but I try to make the question understandable.
In the snippet (Or the jsfiddle) We can find two draggable items:
foo (If you drag it and drop in the Div content editable the [% foo %] text appear where we drop it between the text)
foo2 (This have the Jquery UI drag style (it follows the cursor))
I want to achieve the functionalitty of foo With jquery UI style. But when I try : event.dataTransfer.setData("text/plain", "[%" + event.srcElement.innerHTML + "%]"); It looks like event is not define if I try to define the function like this:
drag: function(ui, event)
The motion of the foo2 Stop work (It mean is a error in the code)
Here is the snippet:
//$( "#foo2" ).draggable();
$( "#foo2" ).draggable({
start: function(ui) {
event.preventDefault();
},
drag: function(ui) {
},
stop: function(ui) {
}
});
var btn = document.getElementById("foo");
btn.onclick = function(event) {
event.preventDefault();
};
btn.ondragstart = function(event) {
event.dataTransfer.setData("text/plain", "[%" + event.srcElement.innerHTML + "%]");
};
<span draggable="true" id="foo" class="btn btn-primary">Foo</span>
<div style="background:red" contenteditable="true" >Put foo between this and this</div>
<a id="foo2" class="btn btn-primary">Foo2</a>
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
The same demo: http://jsfiddle.net/fbprfj5c/1/
Thanks for all your help, recommendations or tips :)
Update:
In response to Gaetano:
I like your idea, and is my fault for no tell all the details. You get the main idea but the tricky way of get the the Width of character and calculate the position with that i can do a similar function to achieve the same effect with a more larger div (in the y axis). But in the div can be more elements than characters. I"ll start with your idea, But i think is a shame open another question for this. In another hand you resolve the problem But that "hacky"/simulation to get the caret position i try to improve (I try before without achieve it), So let"s wait a little is someone have an idea
You may use Droppable for the div element and connect your foo2 draggable element to the droppable.
$('div[contenteditable="true"]').droppable({
drop: function( e, ui ) { // 6.413793103448276
var charWidth = getCharWidth(this);
var position = Math.round(ui.offset.left / charWidth);
position = (position - 1 >= 0) ? position - 1 : position;
$(this).text(function(idx, txt) {
return txt.substr(0, position) + "[%" + ui.draggable.text() + "%]" + txt.substr(position + 1);
})
}
});
$( "#foo2" ).draggable({
connectToSortable: 'div[contenteditable="true"]',
revert: "invalid",
helper: "clone"
});
var btn = document.getElementById("foo");
btn.onclick = function(event) {
event.preventDefault();
};
btn.ondragstart = function(event) {
event.dataTransfer.setData("text/plain", "[%" + event.srcElement.innerHTML + "%]");
};
function getCharWidth(ele) {
var f = window.getComputedStyle(ele)['font'],
o = $('<div>' + ele.textContent + '</div>')
.css({'position': 'absolute', 'float': 'left', 'white-space': 'nowrap', 'visibility': 'hidden', 'font': f})
.appendTo($('body')),
w = o.width() / ele.textContent.length;
o.remove();
return w;
}
<link href="https://code.jquery.com/ui/1.12.0/themes/smoothness/jquery-ui.css" rel="stylesheet"/>
<script src="https://code.jquery.com/jquery-1.12.3.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.0/jquery-ui.js"></script>
<span draggable="true" id="foo" class="btn btn-primary">Foo</span>
<div style="background:red" contenteditable="true" >Put foo between this and this</div>
<a id="foo2" class="btn btn-primary">Foo2</a>
Related
ORIGINAL QUESTION
I've got a draggable element (for the sake of clarity, let's call it $("#draggable")) that triggers a checkbox ($('#checkable')). When $('#draggable') is dragged to a box ($('#droppable')), it checks $('#checkable'), and when $('#draggable') is dragged out of $('#droppable'), it unchecks $('#checkable').
The first time I drag $("#draggable") to $('#droppable'), it checks $('#checkable') perfectly. When I drag $("#draggable") out of $('#droppable'), it unchecks $('#checkable') all fine. But when I redrag $("#draggable") to $('#droppable'), it does not check $('#checkable').
Here's my jQuery code:
$(document).ready(function(e) {
$('.draggable').draggable({ revert: "invalid", opacity: 0.7, helper: "clone" });
$('.droparea').droppable({
accept: function(el) {
if(el.hasClass($(this).data('accept'))) {
return true;
}
},
hoverClass: 'hover',
drop: function(e,ui) {
var $this = $(this);
if(app.is_empty($this.data('count')) || parseInt($this.data('count')) == 0) {
ui.draggable.appendTo($this);
$('#' + ui.draggable.data('rel')).attr('checked','checked');
console.log('#' + ui.draggable.data('rel'),$('#' + ui.draggable.data('rel')).is(':checked'));
} else {
var holder = $('.' + $this.data('accept') + 's');
var child = $this.children('.' + $this.data('accept'));
$('#' + child.data('rel')).attr('checked',null);
child.appendTo(holder);
ui.draggable.appendTo($this);
$('#' + ui.draggable.data('rel')).attr('checked','checked');
}
}
});
$('.holder').droppable({
accept: function(el) {
if(el.hasClass($(this).data('accept'))) {
return true;
}
},
drop: function(e,ui) {
var $this = $(this);
ui.draggable.appendTo($this);
$('#' + ui.draggable.data('rel')).attr('checked',null);
console.log('#' + ui.draggable.data('rel'),$('#' + ui.draggable.data('rel')).is(':checked'));
}
});
});
And here's my HTML:
<div class="drop-holder">
<div class="droparea addressbooks-drop ui-droppable" data-accept="addressbook">
<div class="text-placeholder">
Addressbooks
</div>
</div>
<div class="holder addressbooks ui-droppable" data-accept="addressbook">
<div class="draggable addressbook btn btn-primary ui-draggable ui-draggable-handle" data-rel="4685f5c2-473f-11e5-ad20-000c29b8330c">
Another Book (2124)
</div>
<div class="checkbox-holder">
Another Book (2124)
<input type="checkbox" value="4685f5c2-473f-11e5-ad20-000c29b8330c" id="4685f5c2-473f-11e5-ad20-000c29b8330c">
</div>
<div class="draggable addressbook btn btn-primary ui-draggable ui-draggable-handle" data-rel="04b506c5-4646-11e5-ad20-000c29b8330c">
default (4)
</div>
<div class="checkbox-holder">
default (4)
<input type="checkbox" value="04b506c5-4646-11e5-ad20-000c29b8330c" id="04b506c5-4646-11e5-ad20-000c29b8330c"></div>
</div>
</div>
Any reason why $('#checkable') isn't being checked the second time I drag $('#draggable') to $('#droppable')?
EDIT 1
jsFiddle as per Alex's request. :)
I switched .attr() with .prop() and replaced null with false, and it seems to work.
.prop('checked',true)
Have a look at prop and read when its better to use .prop() than .attr().
As it says in the docs:
Nevertheless, the most important concept to remember about the checked
attribute is that it does not correspond to the checked property. The
attribute actually corresponds to the defaultChecked property and
should be used only to set the initial value of the checkbox. The
checked attribute value does not change with the state of the
checkbox, while the checked property does. Therefore, the
cross-browser-compatible way to determine if a checkbox is checked is
to use the property:
if ( elem.checked )
if ( $( elem ).prop( "checked" ) )
if ( $( elem ).is( ":checked" ) )
I want to dynamically create a draggable div on mousedown, which within the same mousedown event can then be dragged into a droppable area and dropped.
The point that I have got to so far is that a new draggable div is created on mousedown and that div then follows the cursor. But it cannot be dropped into the droppable area.
JS Fiddle here - http://jsfiddle.net/rqyv6bpg/
The jQuery code:
jQuery(document).ready(function ($) {
//on mousedown, creates a new draggable div in the cursor position
$(".search-result-container").mousedown(function(e){
var x = e.pageX + 'px';
var y = e.pageY + 'px';
$('<div/>', {
"class": "test",
text: "Draggable track that can be dropped into droppable queue!",
}).css({
"position": "absolute",
"left": x,
"top": y,
"z-index": 1000
}).draggable()
.appendTo($(document.body))
});
//in order to get the newly created div to instantly follow the cursor
$(document).on('mousemove', function(e){
$('.test').css({
left: e.pageX,
top: e.pageY
});
});
$( "#queue-bar" ).droppable();
});
Help would be greatly appreciated! Thanks in advance.
If I understood correctly, you are looking for the helper option of draggable widget.
$(document).ready(function($) {
$(".search-result-container").draggable({
helper: "clone", // use a clone for the visual effect
revert: false
});
$("#queue-bar").droppable({
accept: "article",
drop: function(event, ui) {
ui.draggable.clone().appendTo(this); // actually append a clone to the droppable
}
});
});
$(document).ready(function($) {
$(".search-result-container").draggable({
helper: "clone", // use a clone for the visual effect
revert: false
});
$("#queue-bar").droppable({
accept: "article",
drop: function(event, ui) {
ui.draggable.clone().appendTo(this); // actually append a clone to the droppable
}
});
});
.search-result-container {
background-color: red
}
#queue-bar {
background-color: blue
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://code.jquery.com/ui/1.9.2/jquery-ui.js"></script>
<article class="search-result-container">This is a track with lots of information</article>
<div id="queue-bar">This is the droppable area</div>
You can also create a custom helper by returning an element to be used as helper as shown below:
$(document).ready(function($) {
$(".search-result-container").draggable({
helper: function(){
// return a custom element to be used for dragging
return $("<div/>",{
text: $(this).text(),
class:"copy"
})
}, // use a clone for the visual effect
revert: false
});
$("#queue-bar").droppable({
accept: "article",
drop: function(event, ui) {
//you might want to reset the css using attr("style","")
ui.helper.clone().appendTo(this); // actually append a clone of helper to the droppable
}
});
});
.search-result-container {
background-color: red;
}
#queue-bar {
background-color: blue;
}
.copy{
background-color: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://code.jquery.com/ui/1.9.2/jquery-ui.js"></script>
<article class="search-result-container">This is a track with lots of information</article>
<div id="queue-bar">This is the droppable area</div>
Updated your fiddle, it works now!!
http://jsfiddle.net/rqyv6bpg/2/
Here is the JS code:
$( ".text" ).draggable({helper:'clone'});
$( "#queue-bar" ).droppable({
drop: function( event, ui ) {
$( this ).append( "<br/>"+ui.draggable.html() );
}
});
On a button click event a new div is created. A user can create as many divs as possible. Once a div is created it becomes draggable thanks to the help of the jqueryui draggable PLUGIN. I have set another on click button event that removes the created div. The problem is that when clicking the user clicks the remove button it removes all divs. How can append a button to each div that specifically removes that div? JSFIDDLE
Jquery
/** Remove newly created div **/
$(".remove").click(function(){
$(".draggable").remove();
});
var z = 1;
$('#button').click(function (e) {
/** Make div draggable **/
$('<div />', {
class: 'draggable ui-widget-content',
text: $('textarea').val(),
appendTo: '.middle-side',
draggable: {
containment: 'parent',
start: function( event, ui ) {
$(this).css('z-index', ++z);
}
}
}).addClass('placement');
/** Contain draggable div **/
$('.middle-side').parent().mousemove(function(e){
var offset = $(this).offset();
var relX = e.pageX - offset.left;
var relY = e.pageY - offset.top;
$('.placement').css({'top': relY + 30,'left': relX + 10, 'position': 'absolute'});
})
});
HTML
<textarea rows="4" cols="50" placeholder="Enter Text Here!"></textarea><br/>
<input type="button" id="button" value="Add Div with Text" />
<button class="remove">Remove div</button><br/>
<div>
<div class="middle-side empty"></div>
</div>
Turn the text property to html:
html: '<span class="close">[X]</span><span class="text">' + $('textarea').val() + '</span>',
Then write click event for .close elements:
$('body').on('click', '.draggable .close', function () {
$(this).closest('.draggable').remove();
});
jsFiddle Demo.
Modify your Add Div Button and Remove Button event like this:
$(".remove").click(function(){
$(".currentDiv").remove();
});
var z = 1;
$('#button').click(function (e) {
$(".currentDiv").removeClass("currentDiv");
/** Make div draggable **/
$('<div />', {
class: 'draggable ui-widget-content',
text: $('textarea').val(),
appendTo: '.middle-side',
draggable: {
containment: 'parent',
start: function( event, ui ) {
$(this).css('z-index', ++z);
},
drag: function() {
$(".currentDiv").removeClass("currentDiv");
$(this).addClass("currentDiv");
},
}
}).addClass('placement currentDiv');
In this way when you create a new div, all currentDiv classes are removed in this line:
$(".currentDiv").removeClass("currentDiv");
Then the currentDiv class is added in created div in last line. So always the last created div has currentDiv class.
Then add this block at the end of your JS:
$('body').on('click', '.draggable', function () {
$(".currentDiv").removeClass("currentDiv");
$(this).addClass("currentDiv");
});
The above block cause that when you click on each draggable element, it selected as current div so Remove button, remove that.
Check JSFiddle Demo
In demo i have also add a background-color:red for currentDiv, you can remove it.
You can simply add this after draggable event :
var closeBtn = '<a href="#xcv" onclick="$(this).unwrap();$(this).remove();" >close</a>';
$('.placement').append(closeBtn);
JSFIDDLE DEMO
I have a set of images placed as position:relative (showing one next to the other).
I use this code to drag and drop them (stolen from the jQuery API documentation, modified to my needs).
$(function() {
$( ".draggable" ).draggable({
start: function(event, ui) {
// Show start dragged position of image.
var Startpos = $(this).offset();
$("div#start").text("START: \nLeft: "+ Startpos.left + "\nTop: " + Startpos.top);
pos_left = Startpos.left; //pos_left is global
pos_top = Startpos.top; //pos_top is also global
},
stop: function(event, ui) {
// Show dropped position.
var Stoppos = $(this).offset();
$("div#stop").text("STOP: \nLeft: "+ Stoppos.left + "\nTop: " + Stoppos.top);
$(this).css('position', "fixed"); //tried absolute and relative, too
$(this).css('left', pos_left);
$(this).css('top', pos_top);
}
});
$( ".droppable" ).droppable({
drop: function( event, ui ) {
id = $(this).attr('id');
alert(id);
}
});
});
What I am trying to do is to return the draggable element to its initial position, after user drops it. However because my elements are relatively positioned the initial left,top coords are the same for all of them (or this is what I understand from the documentation -- I might be wrong here). So although images return, they actually stack each one on top of the other.
What am I doing wrong? What am I supposed to do?
Well. Instead of doing that by yourself use the revert option of the draggable. From the jQuery UI docks:
$( ".selector" ).draggable({ revert: true });
You could make its position relative, top=0px, and left=0px. Worked for me with this code:
$(function(){
$('#draggable').draggable().append('<a href=# class=exit>x</a>');
});
$(function(){
$('.exit').click(function(){
$('#draggable').css({
'top': '0px',
'left': '0px',
'position': 'relative'
});
});
});
I have two jquery.ui draggables. I am constraining their movement to the y-axis. If one is dragged to a certain y-position, I want the other to automatically move to the same y-position and vice versa. Has anyone ever linked two of these together before?
Updated: Script and demo updated so it is no longer restricted to the y-axis while dragging.
This script looks for the class "group" followed by a number to drag/drop these combined objects. I posted a demo here.
HTML
<div class="demo">
<div id="draggable">
<p>Drag from here</p>
<div class="dragme group1"><img src="image1.jpg"><br>Group 1</div>
<div class="dragme group1"><img src="image2.jpg"><br>Group 1</div>
<div class="dragme group2"><img src="image3.jpg"><br>Group 2</div>
<div class="dragme group2"><img src="image4.jpg"><br>Group 2</div>
</div>
<div id="droppable">
<p>Drop here</p>
</div>
</div>
Script
$(document).ready(function() {
// function to get matching groups (change '.group' and /group.../ inside the match to whatever class you want to use
var getAll = function(t) {
return $('.group' + t.helper.attr('class').match(/group([0-9]+)/)[1]).not(t);
};
// add drag functionality
$(".dragme").draggable({
revert: true,
revertDuration: 10,
// grouped items animate separately, so leave this number low
containment: '.demo',
stop: function(e, ui) {
getAll(ui).css({
'top': ui.helper.css('top'),
'left': 0
});
},
drag: function(e, ui) {
getAll(ui).css({
'top': ui.helper.css('top'),
'left': ui.helper.css('left')
});
}
});
$("#droppable").droppable({
drop: function(e, ui) {
ui.draggable.appendTo($(this));
getAll(ui).appendTo($(this));
}
});
});
I haven't done this before, but I suggest using the drag event to adjust the position of the respective other element:
$('.selector').draggable({
...,
drag: function(event, ui) {
},
...
});
The ui object will contain information (in the property ui.offset) you can use to manually reposition the other element.
https://forum.jquery.com/topic/dragging-a-group-of-items-alsodrag-like-alsoresize
I found an extension for UI draggable(). It works in the same way as 'alsoResize' for UI resizable(), i.e.
$('.selector').draggable({ alsoDrag: '.selected' });
Add the plugin code after main jquery-ui library.
$.ui.plugin.add( 'draggable', 'alsoDrag', {
start: function() {
var that = $(this).data("ui-draggable"),
o = that.options,
_store = function (exp) {
$(exp).each(function() {
var el = $(this);
el.data("ui-draggable-alsoDrag", {
top: parseInt(el.css("top"), 10),
left: parseInt(el.css("left"), 10)
});
});
};
if (typeof(o.alsoDrag) === "object" && !o.alsoDrag.parentNode) {
if (o.alsoDrag.length) { o.alsoDrag = o.alsoDrag[0]; _store(o.alsoDrag); }
else { $.each(o.alsoDrag, function (exp) { _store(exp); }); }
}else{
_store(o.alsoDrag);
}
},
drag: function () {
var that = $(this).data("ui-draggable"),
o = that.options,
os = that.originalSize,
op = that.originalPosition,
delta = {
top: (that.position.top - op.top) || 0,
left: (that.position.left - op.left) || 0
},
_alsoDrag = function (exp, c) {
$(exp).each(function() {
var el = $(this), start = $(this).data("ui-draggable-alsoDrag"), style = {},
css = ["top", "left"];
$.each(css, function (i, prop) {
var sum = (start[prop]||0) + (delta[prop]||0);
style[prop] = sum || null;
});
el.css(style);
});
};
if (typeof(o.alsoDrag) === "object" && !o.alsoDrag.nodeType) {
$.each(o.alsoDrag, function (exp, c) { _alsoDrag(exp, c); });
}else{
_alsoDrag(o.alsoDrag);
}
},
stop: function() {
$(this).removeData("draggable-alsoDrag");
}
});
You would have to explicitly set the Y-Axis of both the elements.
For this either in the event handler functions of both the elements you will have to set Y-Axis or bind both the elements with same function.
Happy coding.
Here is a simplified version of the code mentioned in the marked answer(for dummies like me):
In HTML
<div id="div1" class="group">...</div>
<div id="div2"class="group">...</div>
In Script tag
$(document).ready(function(){
//to get the group
var getGroup = function() {
return $(".group");
}; // add drag functionality
$(".group").draggable({
revertDuration: 10,
// grouped items animate separately, so leave this number low
containment: "window",
scroll: false,
stop: function(e, ui) {
getGroup(ui).css({
'top': ui.helper.css('top'),
});
},
drag: function(e, ui) {
getGroup(ui).css({
'top': ui.helper.css('top'),
'left': ui.helper.css('left')
});
}
});
});