How to find previously dropped value from droppable div - javascript

I am working on dynamic formula generator using jquery drag and drop functionlaity
What i have done so far is
I have two 2 list
<ul id="head">
<li class="horizontal">Salary</li>
<li class="horizontal">Workers</li>
<li class="horizontal">Perday</li>
</ul>
and
<ul id="operations">
<li class="horizontal">Add +</li>
<li class="horizontal">Sub -</li>
<li class="horizontal">Multiply *</li>
<li class="horizontal">Divide /</li>
</ul>
The process is user will first drag from first list and drop in droppable div and they will add anything from operations list like (+,- etc..).
The Jquery i have used :
$('#head li').draggable({
cursor: 'move',
helper: 'clone',
connectToSortable: "#drop",
});
$("#drop").droppable({
drop: function (event, ui) {
$(this)
.removeClass("ui-droppable ui-sortable")
.addClass("horizontal ui-draggable ui-draggable-handle")
}
}).sortable();
droppable div
<div id="drop" style="border:2px solid;min-height:100px;"></div>
My Problem is that i have to validate user should not drop more than one operations at a time. ex:Multiply * Add + this is wrong. The operations must come between 2 text. so how i can we find the previously added value in this droppable div (drop).
Thanks in advance

How about using some data attribiutes to id your operations and a variable in js to store what was dropped last, like this:
HTML
<div class='js-droppable' data-drop-type='op'>operation 1</div>
JS
var lastDropped = '';
var processDroppable = function () {
var dropped = $(this).data('drop-type');
if (lastDropped == 'op' && dropped == 'op') {
console.log('not allowed')
} else {
console.log('you may drop ...');
}
lastDropped = dropped;
}
$('.js-droppable').click(processDroppable);
The data attribute stores the type of droppable and then is used to catch any duplicate droppable that is not allowed.
You could do any logic really based on identifying your droppables, but lastDropped == 'op' && dropped == 'op' covers the case in the question.
The working example is here in JSFiddle, I've used click events rather than dropped events, for simplicity; open the console to see the output.

Related

Empty list message on jquery-sortable

I'm working with jquery-sortable and I'm having some difficulty modifying the list container (ul) when it's been emptied or loaded empty. For example, If you have two containers:
A collection list to drag from that always contains a few items.
A destination list which loads empty (unless it is being edited and it will contain some list items but can be emptied by dragging them out of there
The empty container (ul) should display a message (i.e. nothing here) whenever it loads empty or it gets emptied on edit.
I tried several approaches with no avail.
SAMPLE HTML FOR EMPTY CONTAINER
<ul id="mediaItemsListDest" class="playlist-items connectedSortable">
<!-- force a message in html -->
<p>Drag and drop an item from the list</p>
</ul>
DIFFERENT JQUERY APPROACHES
if( $("#mediaItemsListDest li").length >= 1 ) {
//remove it when the ul contains an li
$("#mediaItemsListDest p").css('display','none');
}
or
if( $("#mediaItemsListDest li").length === 0 ) {
//no li is found, display a message via jquery but don't add it as a <p> element in the html
$(this).html("Sorry, this is empty");
}
or
if( !$("#mediaItemsListDest").has("li").length ) {
$(this).html("Sorry, this is empty");
}
None of them worked. How else can I hijack this empty or emptied list?
Here's a testing fiddle for you:
DEMO
Thanks in advance.
You need to handle on every list change the error message state so let's say we have the following HTML - example from your demo:
<ol id="mediaItemsListDest" class="simple_with_animation vertical">
<p>Drag and drop an item from the list</p>
<li>Item 1</li>
<li>Item 2</li>
</ol>
Additionally I have extended with a function which is handling the message state, code is placed on initialization part of the application:
function handleMessage() {
let liObjects = $('#mediaItemsListDest li');
let message = $('#mediaItemsListDest p');
console.log('length', liObjects.length);
console.log('message', message);
if (liObjects.length !== 0) {
message.css('display', 'none');
} else {
message.css('display', 'inline');
}
}
handleMessage();
This function needs to be called in onDrop event:
onDrop: function ($item, container, _super) {
// code part removed but you can find in your demo
handleMessage();
}
I did a quick test and it was working fine. I hope this one is helping, let me know if you need more information.

Unable to Drop on an Empty List

I am making a simple web app. At one part I have to drag among two different lists - One of which may be empty. I am not able to drop to an empty list.
I have tried:
dropOnEmpty = true
dropOnEmpty = "true"
dropOnEmpty = false
dropOnEmpty = "false"
and tried stuff as on:
How do I move an item to an empty list using jquery?
JQuery API
Rollys Wordpress
jQuery UI drop on empty container/list not working
Hidden <li> elements so that lists are not empty at all.
but nothing worked.
This is the HTML part:
<ul><li>Present</li></ul>
<ul id="present" class="sortable"></ul> //First List
<ul><li>Future</li></ul>
<ul id="future" class="sortable"><li></li></ul> //Second List
This is the jQuery function:
$("ul.sortable").sortable({
axis: 'y',
cancel: "div.cal",
connectWith: "ul",
dropOnEmpty: true,
update: function(event, ui) {
if (ui.sender === null) {
var goalsNames = '';
$(".sortable li").each(function() {
if (goalsNames === '') {
goalsNames = '["' + $(this).text();
} else {
goalsNames += '","' + $(this).text();
}
});
goalsNames += '"]';
localStorage.setItem("goalsNames", goalsNames);
var goalsDetails = localStorage.getItem("goalsDetails");
console.log(goalsDetails);
var goalsDetailsObj = JSON.parse(goalsDetails);
$("#present li").each(function() {
console.log(JSON.stringify(goalsDetailsObj[$(this).text()]));
console.log(goalsDetailsObj[$(this).text()].active);
goalsDetailsObj[$(this).text()].active = "present";
});
$("#future li").each(function() {
goalsDetailsObj[$(this).text()].active = "future";
});
localStorage.setItem("goalsDetails", JSON.stringify(goalsDetailsObj));
}
}
}).disableSelection();
});
As far as I know, sortable is a JQuery-UI feature to sort items within one list via drag and drop.
From the docs
Enable a group of DOM elements to be sortable. Click on and drag an element to a new spot within the list
I would try to go with draggable and droppable and you need to initialize a drop target via droppable.
<ul><li>Present</li></ul>
<ul id="present" class="firstList"></ul> <!--First List-->
<ul><li>Future</li></ul>
<ul id="future" class="secondList"><li></li></ul> <!--Second List-->
$('ul.firstList').draggable(/***/);
$('ul.secondList').droppable(/***/);
And read about the many options to be inserted at /***/.
Update
I created a plunker for you as a start point: http://plnkr.co/RPlTgK
Here is the proper example for drag and drop among empty list hope this will help Demo

How to display the new order of the parent after sorting?

Here are my current codes. These codes sort both parent and child but it display only the new order of the child after sorting.
template
<div id="tree">
<ul id="envelopes" class="dropcat cat-data">
<li id="1">
<span class="cat-title">Utilities</span>
<ul class="dropenv mt">
<li class="innerList">Electricity</li>
<li class="innerList">Water</li>
<li class="innerList">Trash</li>
<li class="innerList">Television</li>
</ul>
</li>
<li id="2">
<span class="cat-title">Sample</span>
<ul class="dropenv mt">
<li class="innerList">Test</li>
</ul>
</li>
<li id="3">
<span class="cat-title">Saving</span>
<ul class="dropenv mt">
<li class="innerList">College Fund</li>
<li class="innerList">Retirement Fund</li>
<li class="innerList">Emergency Fund</li>
</ul>
</li>
</ul>
</div>
<p id="cl"></p>
js
<script>
var addPositions = function() {
$('.dropenv, .dropcat').each(function() {
var position = 0;
$(this).children().each(function() {
$(this).data('position', position);
position++;
});
});
};
$(document).ready(function() {
addPositions();
var origTitle;
var origColor;
$(".dropenv").sortable({
connectWith: "ul.mt",
dropOnEmpty: true,
start: function(event, ui) {
origColor = ui.item.text();
origTitle = ui.item.parent().siblings('.cat-title').text();
},
stop: function(event, ui) {
var order = [];
ui.item.closest('ul').children('li').each(function() {
order.push($(this).data('position'));
var c = $(this).text();
if (c === origColor) {
var z = origTitle;
} else {
var z = $(this).parent().siblings('.cat-title').text();
}
$("#cl").append(z + "_" + c + "<br /\>");
});
}
});
$( "ul.dropcat").sortable({
connectWith: "ul.cat-data",
dropOnEmpty: true,
});
});
</script>
How to get the new order of the parent?
For example:
Before:
- Utilities
- Sample
- Saving
//If I'm going to swap Saving to Utilities, it must be display the new order like this
New Order:
- Saving
- Sample
- Utilities
Update from #Jack Shedd
I copy the stop and I get this output:
_ Utilities Electricity Water Natural Gas Home Phone Cell Phones Trash Television Internet
_ Charity/Giving Charitable Gifts Fast Offerings
_ Sample test
_ Recreation Entertainment Vacation
_ Saving College Fund Emergency Fund Retirement Fund
How to get parent only, no child?
Based on the code and the question:
You have a custom stop event handler on your sortable object which, after the user stops dragging, will append the new position of the child to the innerHTML of the #cl paragraph tag.
You're wondering why this works for the children, but not the parent.
If you look at your jQuery, you'll see this line:
$(".dropenv").sortable({
This is applying the sortable behavior to any element with a class of .dropenv. It's here that you're initing the custom stop event handler which updates the #cl tag.
However, you're only applying this behavior to elements with a class of .dropenv, which, reviewing your html for the parent:
<ul id="envelopes" class="dropcat cat-data">
The parent UL doesn't match.
Instead, you're applying an entirely new sortable behavior to the parent:
$( "ul.dropcat").sortable({
connectWith: "ul.cat-data",
dropOnEmpty: true,
});
Which has none of the custom stop handler code contained within it.
So either copy the stop handler code from the .dropenv sortable options into the one above, or make the .dropenv sortable apply to your .dropcat UL as well.

How to build a Drag and Drop Menu Builder?

Hi all i present i am wokring on Menu Builder,where user can come build his menu how ever he likes with the subemnus to,i have a problem in Drag and Drop, i had done till drag but drop is not working in my case
i have to achevie some thing like this
http://www.prodevtips.com/demos/drag_drop_tree/
but not similar i should be able to create a chain or tree with drag and drop,my scenario is i have all menus listed at the bottom and and add column button at the top,when user wants to build menu he can click on addmenu button and a column opens there he can drag and drop the menus from the listed menu, from here i want the working scenario of the above link i had given where if i drop on any menu item it should be the child of that parent menu item which the user dropped on
here is my script
$(document).ready(function() {
var i = 0;
$("button[id='columnadd']").click(function () {
alert(1);
var domElement = $('<aside id="shoppingCart' + i + '" class="shoppingCart"><h2 class="ui-widget-header">Add Menu Items Here</h2><aside class="ui-widget-content"><ol><li class="placeholder">Add your items here</li></ol></aside></aside>');
i++;
$(this).after(domElement);
});
$(".small_box li" ).draggable({
appendTo: "body",
helper: "clone"
});
});
$(".small_box li a").droppable({
tolerance : "pointer",
hoverClass : "tree_hover",
drop : function(event, ui){
var dropped = ui.draggable;
dropped.css({top: 0, left: 0});
var me = $(this).parent();
if(me == dropped)
return;
var subbranch = $(me).children("ul");
if(subbranch.size() == 0) {
me.find("a").after("<ul></ul>");
subbranch = me.find("ul");
}
var oldParent = dropped.parent();
subbranch.eq(0).append(dropped);
var oldBranches = $("li", oldParent);
if (oldBranches.size() == 0) { $(oldParent).remove(); }
}
});
and here is my html
<body>
<button id="columnadd" >Add Column</button>
<aside class="menu-structer" id="AddColumns" >
</aside>
<aside class="small_box">
<h4>BRANDS</h4>
<ul>
<li id ="brand1"><a class="" href="#">Brand1</a></li>
<li id ="brand2">Brand2</li>
<li id ="brand3">Brand3</li>
<li id ="brand4">Brand4</li>
</ul>
</aside>
<aside class="small_box">
<h4>CATEGORIES</h4>
<ul>
<li id ="category1">Category1</li>
<li id="category2">Category2</li>
<li id="category3">Category3</li>
<li id="category4">Category4</li>
</ul>
</aside>
<aside class="small_box">
<h4>PRODUCTS</h4>
<ul>
<li id="Product1">Product1</li>
<li id="product2">Product2</li>
<li id="product3">Product3</li>
<li id="product4">Product4</li>
</ul>
</aside>
</body>
can any one help me over here please...that would be of a a great help for me..i am struggling with the Drop Event
Mistakes i had done
I had created a DOM Element (which is the drop area) upon click and this element is not in your page until you click the trigger. By doing $('#shoppingCart ol').droppable({...}) in $(document).ready(function() {}) block you try to add droppable to an element that even not in your page, so this won't do a thing.
changes
What i had done is make the element droppable after create that element
$("button[id='columnadd']").click(function () {
// create the element
var domElement = $('<aside id="shoppingCart' + i++ + '" class="shoppingCart"><h2 class="ui-widget-header">Add Menu Items Here</h2><aside class="ui-widget-content" id="droppable"><ol><li class="placeholder">Add your items here</li></ol></aside></aside>');
// put it after $(this)
$(this).after(domElement);
// at this point you have domElement in your page
// make it droppable
domElement.find("ol").droppable({
// put options here
greedy: true,
drop: function (event, ui) {
makeItDroppableToo(event, ui, this);
}
});
});
and this is the function to make your dropped element has its own placeholder
function makeItDroppableToo(e, ui, obj) {
$(obj).find(".placeholder").remove();
var placeholder = $("<ol><li class='placeholder'>You can also drop it here</li></ol>");
$("<li></li>").append(ui.draggable.text()).append(placeholder).appendTo($(obj));
// this is the same as the previous one
placeholder.droppable({
// put options here
greedy: true,
drop: function (event, ui) {
makeItDroppableToo(event, ui, this);
}
});
}

jQuery UI get the sorted position of LI element in UL

I'm using jQuery UI's sortable for my UL list. Each time the user sorts the list, I want each li element to update it's "position" attribute to it's position in the list.
<ul>
<li position="1">a</li>
<li position="2">b</li>
<li position="3">c</li>
</ul>
So when a user swaps c with a, the position will also update. I tried to use .each but it seems that javascript doesn't follow the order of how the LI elements are displayed but the order of the element's creation.
As mentioned in another answer, using update is all you need:
$(function() {
var $sortable = $('ul').sortable({
update: function(event, ui) {
var counter = 1;
$('li', $sortable).each(function() {
$(this).attr('position', counter);
counter++;
});
}
});
});
Example link
Have you tried :eq selector or index method? Provided you know which li element you're trying to find the position of you could find the position like so:
<ul>
<li id="c">c</li>
<li id="b">b</li>
<li id="a">a</li>
</ul>
var position = $('li#b').index();
You'll want to take advantage of the Sortable "update" event:
$( "ul" ).sortable({
update: function(event, ui) {
var order = $(this).sortable('serialize');
console.info(order);
}
});
You can then use the "serialize" method to pull the updated order of items. One requirement for this to work is that the IDs of each list item contain an underscore, so you'd want to update your HTML to:
<ul>
<li id="position_1">a</li>
<li id="position_2">b</li>
<li id="position_3">c</li>
</ul>

Categories