jquery draggable & droppable get source container (that draggable came from) - jquery-ui

I made this jsfiddle for a different answer and I'm wondering how I can get the souce container that the droppable came from
http://jsfiddle.net/d7wsz/8/
The jquery is
$("#Table1 tr:not(.disabled), #Table2 tr:not(.disabled), #Table3 tr:not(.disabled)").draggable({
helper: 'clone',
revert: 'invalid',
start: function (event, ui) {
$(this).css('opacity', '.5');
},
stop: function (event, ui) {
$(this).css('opacity', '1');
}
});
$("#Table1, #Table2, #Table3").droppable({
drop: function (event, ui) {
$(ui.draggable).appendTo(this);
alert($(ui.draggable).text() +
' was draged from ' +
'XX' + ' to ' +
$(this).attr('id') + '.');
}
});
and the html is
<h1>Table 1</h1>
<table id="Table1">
<tr><td>Row 3</td></tr>
<tr class='disabled'><td>Row 4</td></tr>
<tr><td>Row 5</td></tr>
</table>
<h2>Table 2</h2>
<table id="Table2">
<tr><td>Row 8</td></tr>
<tr class='disabled'><td>Row 9</td></tr>
<tr><td>Row 10</td></tr>
</table>
<h2>Table 3</h2>
<table id="Table3">
<tr><td>Row 11</td></tr>
<tr><td>Row 12</td></tr>
</table>

You can use a variable which you set in the start event of the draggable and get that info in the stop event of the droppable.
$(function () {
var sourceElement;
$("#Table1 tr:not(.disabled), #Table2 tr:not(.disabled), #Table3 tr:not(.disabled)").draggable({
helper: 'clone',
revert: 'invalid',
start: function (event, ui) {
$(this).css('opacity', '.5');
//NEW
sourceElement = $(this).closest('table').attr('id');
},
stop: function (event, ui) {
$(this).css('opacity', '1');
}
});
$("#Table1, #Table2, #Table3").droppable({
drop: function (event, ui) {
$(ui.draggable).appendTo(this);
//alert sourceElement
alert($(ui.draggable).text() +
' was draged from ' + sourceElement + ' to ' + $(this).attr('id') + '.');
}
});
});
See my updated jsfiddle
If you have more than those tables on your page you might think about giving them a class to properly identify them.

Related

Change HTML when on start dragging with Jquery UI

I've been working on a drag and drop UI with jquery UI.
I have a bunch of elements like this, that are draggable:
<i class="fa fa-laptop fa-fw"></i> Server
I can drag and clone this onto a drop zone. But when I start dragging the original element, I want to change the HTML to be
<i class="fa fa-laptop fa-5"></i>
The current code looks like this, but should I be doing something in the start event handler to clone, and change the html of the cloned element?
function MakeDraggable(ele) {
ele.draggable({
grid: [20, 20 ],
//revert: "invalid",
helper: 'move'
});
}
$(function() {
// Make the .draggable class a Draggable
//
$( ".draggable" ).draggable({
grid: [ 20, 20 ],
helper: 'clone',
appendTo: '#dropzone-panel',
start: function(event, ui) {
console.log("Dragging me.....");
}
});
// Setup the dropzone
//
$("#dropzone-panel").droppable({
drop: function(event, ui) {
console.log("Drop Event Fired");
// Get the original element id
var id = ui.draggable.attr("id");
// If this element is a copy already
// then dont clone it.
//
if (id.indexOf("-copy-") >= 0) {
console.log("This is a copy");
} else {
// This is the orginal, so clone and create a new id
var number_of_clones = document.querySelectorAll('*[id^="'+id+"-copy-" +'"]').length;
console.log("found [" +number_of_clones +"] copies");
var pos = ui.position;
var $obj = ui.draggable.clone().attr("id", id+"-copy-"+number_of_clones);
$obj.css({
position: 'absolute',
top: pos.top + "px",
left: pos.left + "px"
});
$obj.appendTo("#dropzone-panel");
// Make the clone draggable
MakeDraggable($obj);
}
}
});

CKEditor 4 and jQuery UI sortable removes content after sorting

I've ran into an issue with CKEditor 4 and jQuery UI's sortable method where if I sort a container that has a CKEditor instance, it removes the value and throws an error "Uncaught TypeError: Cannot call method 'getSelection' of undefined". It also makes the editor uneditable. I was able to get around this in CKEditor 3 with one of the following hacks found here:
CKEditor freezes on jQuery UI Reorder
In looking at the Chrome DOM inspector, it appears that the contents of the iframe are removed.
Below is crude test code:
<html>
<head>
<title>test</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.24/jquery-ui.min.js"></script>
<script src="ckeditor.js"></script>
<script type="text/javascript">
$(function(){
var tmpStore = {};
$('#sortable').sortable({
cursor: 'move',
// Hack that use to work on V3 but not on V4:
// https://stackoverflow.com/questions/3379653/ckeditor-freezes-on-jquery-ui-reorder
start:function (event,ui) {
$('textarea').each(function(){
var id = $(this).attr('id');
tmpStore[id] = CKEDITOR.instances[id].getData();
})
},
stop: function(event, ui) {
$('textarea').each(function(){
var id = $(this).attr('id');
CKEDITOR.instances[id].setData(tmpStore[id]);
})
}
});
$('textarea').each(function(){
var ckId = $(this).attr('id');
config = {};
CKEDITOR.replace(ckId, config);
})
})
li { padding: 10px; width: 800px; height: 300px; }
</head>
<body>
<ul id="sortable">
<li><textarea id="test1" name="test1">test1</textarea></li>
<li><textarea id="test2" name="test1">test2</textarea></li>
<li><textarea id="test3" name="test1">test3</textarea></li>
</ul>
</body>
</html>
I was facing the same problem and have fixed based on answers here. Please see fiddles below
ISSUE:
https://jsfiddle.net/33qt24L9/1/
$(function() {
$( "#sortable" ).sortable({
placeholder: "ui-state-highlight"
});
CKEDITOR.replace( 'editor1' );
CKEDITOR.replace( 'editor2' );
CKEDITOR.replace( 'editor3' );
CKEDITOR.replace( 'editor4' );
});
RESOLVED ISSUE: https://jsfiddle.net/57djq2bh/2/
$(function() {
$( "#sortable" ).sortable({
placeholder: "ui-state-highlight",
start: function (event, ui)
{
var id_textarea = ui.item.find(".ckeditor").attr("id");
CKEDITOR.instances[id_textarea].destroy();
},
stop: function (event, ui)
{
var id_textarea = ui.item.find(".ckeditor").attr("id");
CKEDITOR.replace(id_textarea);
}
});
CKEDITOR.replace( 'editor1' );
CKEDITOR.replace( 'editor2' );
CKEDITOR.replace( 'editor3' );
CKEDITOR.replace( 'editor4' );
});
EDIT: If like me you had seperate configs per editor here's updated code that will help:
start: function (event, ui)
{
$('.wysiwyg', ui.item).each(function(){
var tagId = $(this).attr('id');
var ckeClone = $(this).next('.cke').clone().addClass('cloned');
ckeConfigs[tagId] = CKEDITOR.instances[tagId].config;
CKEDITOR.instances[tagId].destroy();
$(this).hide().after(ckeClone);
});
},
stop: function(event, ui) {
// for each textarea init ckeditor anew and remove the clone
$('.wysiwyg', ui.item).each(function(){
var tagId = $(this).attr('id');
CKEDITOR.replace(tagId, ckeConfigs[tagId]);
$(this).next('.cloned').remove();
});
}
Thanks to: https://github.com/trsteel88/TrsteelCkeditorBundle/issues/53
You have to re-create CKEditor once underlying DOM structure is modified. Save editor data with editor.getData() before editor.destroy() and restore contents with editor.setData( data ) once you create a new instance. There's no other way to fix this since CKEditor strongly depends on the DOM structure.
Remove CKEditor start Sortable
var ckeConfigs = [];
$('.ui-sortable').sortable({
start:function (event,ui) {
$('.lineItemCommentBox', ui.item).each(function(){
var tagId = $(this).attr('id');
ckeConfigs[tagId] = CKEDITOR.instances[tagId].config;
CKEDITOR.instances[tagId].destroy();
});
},
stop: function(event, ui) {
$('.lineItemCommentBox', ui.item).each(function(){
var tagId = $(this).attr('id');
CKEDITOR.replace(tagId, ckeConfigs[tagId]);
});
}
});
The code below works for me, we have to destroy the editor on start and recreate it when the drag is ended getting the value of the textarea which come the data from :
jQuery(function($)
{
var panelList = $("#nameofyourdiv");
panelList.sortable(
{
handle: ".classofyourdivforsorting",
start: function (event, ui)
{
var id_textarea = ui.item.find("textarea").attr("id");
CKEDITOR.instances[id_textarea].destroy();
}
stop: function (event, ui)
{
var id_textarea = ui.item.find("textarea").attr("id");
CKEDITOR.replace(id_textarea);
}
});
});
Hope it helps someone.
i ve solved this kind of problem by instantiating the CKEditor after having opened the jquery dialog
I had the Similar issue with CKEDITOR , The Code Below worked for me. Destroy the Ckeditor instance and Remove the Ckeditor and when the dragging ends replace the current textarea with Ckeditor again
$("#sortable").sortable({
items: '.dynamic',
start: function (event , ui) {
var editorId = $(ui.item).find('.ckeditor').attr('id');// get the id of your Ckeditor
editorInstance = CKEDITOR.instances[editorId]; // Get the Ckeditor Instance
editorInstance.destroy(); // Destroy it
CKEDITOR.remove(editorId);// Remove it
},
stop: function(event, ui) {
var editorId = $(ui.item).find('.ckeditor').attr('id');// Get the Id of your Ckeditor
CKEDITOR.replace(editorId);// Replace it
}
}
});
$("#sortable").disableSelection();
Here #sortable is the id of the DIV which is sortable and '.dynamic' is the Class assigned to DIV that are eligible to sort and '.ckeditor' is the class for the Textarea .
I got my solution from Here , Hope this helps for someone in future.
I simply use the ckeditorOff() and ckeditorOn() functions to keep data and re/de-instance ckeditor instances during movement.
$('#sortable').sortable({
cursor: 'move',
start:function (event,ui) {
if(typeof ckeditorOff=='function')ckeditorOff();
},
stop: function(event, ui) {
if(typeof ckeditorOn=='function')ckeditorOn();
}
});
I put the typeof ckeditorOff statement to make the code compatible with future versions of ckeditor in case they decide to remove these two functions.

Autocomplete response

I'm trying to 'popup' jquery autocomplete result under a textbox using the popover components of bootstrap.
I render results of the autocomplete query in an hidden div (#wrapper) and I want on render completion to set the content of my popover and show it.
For this I've overloaded the _renderItem function which append my results' divs inside the hidden container (#wrapper).
I thought the response function is called when _renderItem calls are done but I'm missing something as response function is never called.
Any solution?
Thanks!
$("#bookSearch")
.autocomplete({
minLength: 0,
source: '/Autocomplete/Books',
focus: function (event, ui) {
$("#bookSearch").val(ui.item.label);
return false;
},
search: function(event, ui) {
$('#wrapper').empty();
},
response: function (event, ui) {
$('#bookSearch').popover('destroy');
$('#bookSearch').popover({
html: true,
placement: 'bottom',
content: $('#wrapper').html()
});
$('#bookSearch').popover('show');
}
})
.data("autocomplete")._renderItem = function (ul, item) {
$('<div class="media"></div>')
.data("item.autocomplete", item)
.append("<a class=\"pull-left\" href=\"#\"><img class=\"media-object\" src=\""
+ item.ImgUrl
+ "\"></a><div class=\"media-body\"><h6 class=\"media-heading\">"
+ item.Name
+ "</h6>"
+ item.Author + "</div>").appendTo('#wrapper');
};
I fixed the problem by adding to my css file a z-index style for the autocomplete.
.ui-autocomplete {
z-index: 10000;
}
Remember to set a higher value for the z-index if it is necessary. Just for the record I have something like this in the HTML file
<div class="ui-widget">
<label for="employee">Employee:</label>
<input id="employee" type="text" name="employee" />
</div>

jquery UI "drop" have conflict with “sortable”?

My html is:
<div id="sortable">
<div class="node"></div>
<div class="node"></div>
<div class="node"></div>
<div class="node"></div>
</div>
My script is:
$('.node').droppable({
drop: function (e, ui) {
alert("drag finish");
}
});
$('#sortable').sortable({
stop: function (e, ui) {
alert("sort finish!");
}
});
But when I drag an element and sort, it only hits alert("drag finish") but not alert("sort finish").
Why is this happening? How can I solve this problem?
Here is the example http://jsfiddle.net/GRWDR/1/
i myself created a fiddle to test your problem and
see it here it is working fine
notice i load the scripts on dom ready i.e. i think you should enclose your scripts in dom.ready block
$(document).ready(function(){
$('.node').droppable({
drop: function (e, ui) {
alert("drag finish");
}
})
$('#sortable').sortable({
stop: function (e, ui) {
alert("sort finish!");
}
});
});
Hope this help you

Jquery draggable makes input text fields uneditable (swallows onfocus?)

I have written code (below) to be able to drag an input field onto another, but it seems that draggable swallows input[text].onfocus.
This results in the problem, that all draggable input fields act as disabled (firefox) and clicking the mouse does not focus them. I can edit the input field if I focus on them using the TAB key, but I have to traverse all the necessary tab-indexes.
So it seems draggable swallows the input[text].onfocus mouse event.
Is there a way to workaround this during bind-time?
<head>
<script type="text/javascript" src="/js/jquery.js"></script>
<script type="text/javascript" src="/js/jquery-ui.js"></script>
<script type="text/javascript">
$(document).ready( function()
{
$("#drag-table tr td input").draggable({helper: 'clone', revert: 'invalid', cancel: null, cursor: 'move', addClasses: false, containment: $("#drag-table"), handle: 'h2', opacity: 0.8, scroll: true });
$("#drag-table tr td input").droppable({
addClasses: false,
drop: function(ev, ui) {
alert('value='+ ui.draggable.val() + ", text=" + ui.draggable.text() + " and deeper=" + ui.draggable[0].value);
$(this).insertAtCaret(ui.draggable.val());
ui.draggable.val(null);
$(this).trigger('change');
}
});
});
$.fn.insertAtCaret = function (myValue) {
return this.each(function(){
//IE support
if (document.selection) {
this.focus();
sel = document.selection.createRange();
sel.text = myValue;
this.focus();
}
//MOZILLA / NETSCAPE support
else if (this.selectionStart || this.selectionStart == '0') {
var startPos = this.selectionStart;
var endPos = this.selectionEnd;
var scrollTop = this.scrollTop;
this.value = this.value.substring(0, startPos)+ myValue+ this.value.substring(endPos,this.value.length);
this.focus();
this.selectionStart = startPos + myValue.length;
this.selectionEnd = startPos + myValue.length;
this.scrollTop = scrollTop;
} else {
this.value += myValue;
this.focus();
}
});
};
</script>
</head>
<body>
<table border="1" cellspacing="10" cellpadding="10" id="drag-table">
<tr>
<td><input type="text" name="1x1y" id="id1x1y" value="text" onfocus="alert('onfocus swallowed?');"/></td>
<td><input type="text" name="2x1y" id="id2x1y" onchange="alert('hello');"/></td>
</tr>
<tr>
<td><input type="text" name="1x2y" id="id1x2y" value="next"/></td>
<td><input type="text" name="2x2y" id="id2x2y"/></td>
</tr>
</table>
</body>
Wrap the element in either a div or span (depending on which would be valid) and apply the draggable event on that instead.

Resources