I am searching through "drag & drop sortable" Javascript libraries such as Prototype's sortable, JQuery's sortable, and a number of standalone ones.
I feature that I can't find (but know it's out there) is, I can't think of a better word, "delayed" sorting so that when I move an item around on the list, it will not be moved immediately, but a line or other kind of marker will appear showing where the item would end up if I dropped it right now. This functionality can for example be found in Windows when moving items around in the start menu.
Could anybody point me towards a Javascript solution that can do this? Prototype or standalone would be preferred for the current project, but JQuery is fine as well.
Take a look at script.aculo.us Sortables and property called ghosting.
Refer:
https://github.com/madrobby/scriptaculous
http://madrobby.github.io/scriptaculous/sortable-create/
I use jQuery to do this in one of my projects.
On the list element, lets say an element , I assign the class sortable:
<ul class="sortable">
Then I've a Javascript function like this:
$(function() {
$( ".sortable" ).sortable({
placeholder: "placeholder-sortable",
update: function(event, ui) {
var listElements = $(this).sortable('toArray');
//Your code
}
});
$( ".sortable" ).disableSelection();
With this the new order is saved into the variable listElements, in which there are stored the ids of the different li items.
Related
I am working on a custom workflow style application. I am using jQuery UI for a drag and drop toolkit.
On dropping an item, I am rendering a bootstrap panel with various items in the body (depending on what was dropped).
Now, what I would like to do is allow these panels to be draggable again within the drop area, but I can't seem to achieve it.
Below is a link to the gist of the html. Ignore the linkme stuff, that's another aspect i'm working on. Ideally, the objects would be draggable anywhere within the solutions div.
https://gist.github.com/ajberry/0ab2c0adca4f92855b26b63f929b108d
I'm assuming it's something daft, and I have tried the following with no success:
$( ".panel-default" ).draggable();
As I thought this would allow each panel to be draggable. I'm guessing it's to do with my droppable event or something.
Regards
I added in the draggable attribute on the drop event. As prior to that the objects didn't exist so couldn't apply it.
function handleDropEvent( event, ui ) {
var rownum = $("#solution .panel-default").length;
console.log(rownum);
var draggable = ui.draggable;
var mytype = draggable.attr('class');
if (!(mytype.includes("panel-default"))){
renderChildControls(draggable.attr('id'), rownum)
}
$('.panel-default').draggable();
}
So I currently am attempting to make my first website (so forgive me for the very sloppy code!) and am having a bit of trouble getting the draggable function to work how I want it to.
This is the first part where I create the divs and set all of the information to how I want it to be. Basically it's using an api to get item information from a game and then is making a display for that item.
<div class='item' id='item"+itemid+"' title='Item'>\n<div class='item_image'><img src='http://ddragon.leagueoflegends.com/cdn/5.2.1/img/item/"+item.image.full+"' style='z-index: 1;position: absolute;'><img src='images/item_border.png' style='z-index: 2;position: absolute;'></div>\n<div class='item_name'>"+item.name+"</div><br>\n<div class='item_cost'><img src='images/gold.png'> "+item.gold.total+"</div></div><br>\n
I then tried to make the whole "itemid" div draggable, but when it's dragged I only want the item image to be shown under your cursor, not the whole div. If I understand this correctly, that's what the "appendTo" is used for:
$("#item"+itemid).draggable({
containment: "window",
appendTo: "#item"+itemid+" .item_image",
helper: "clone",
distance: 25,
opacity: .8,
scroll: false,
stack: "div",
revert: true
});
However whenever I try to drag something using this, it shows not just the item image+the border, but also the item name and item cost, although the gold image is at a bigger scale than it normally is when not being dragged.
How would I make it work so it only shows the image, and not the whole thing when being dragged? Also, why is it showing the whole div if the one I selected for the appendTo is only the image?
Thanks in advance!
The question: "How appendTo works in Draggable()?"
I will try to answer that.
the short answer is "Which element the draggable helper should be appended to while dragging." If you have problem understanding this sentence (like I had) let me explain it:
To explain appendTo I have to explain helper first, because they are kind of related to each other. when you start dragging an element using helper, you have three options:
1- helper: 'original' //default
2- helper: 'clone'
3- helper: function(){ return "an element" }
1 - The first option is "default" and it means the dragging element is the element itself and it has it's own position in the DOM TREE and appendTo option doesn't work in this situation. The element doesn't append to anything, it is in the same situation as before in the DOM TREE.
2 - The second option is "clone" and it means the dragging element is not the same element you start to drag, it's another element copied from the first one. Now, since we can't have an orphan element, who is the parent of the new copied element? well you should answer this in the appendTo option.
3 - The third option is "an element" returning from a function. It is something like:
helper: function(){ return $("<p>YES</p>"); }
And again this new "p" can't be an orphan element so again we attach it to an element which is selected in appendTo option.
At the end you should know that the appendTo is just doing his job while you are dragging the element and after dropping the helper will gone (unless you attach it to an element) and the appendTo will finish his job.
This is quite a complicated question so I am not looking for "full examples", but instead ideas of implementing a solution to my problem.
I am creating a drag-and-drop page where users can drag and drop tools into their workspace. This is currently working fine through the implementation of draggable() (jQuery UI).
However, the system is getting complicated with new features I am implementing:
When dragged onto the workspace, the user can freely move the items around their page. However I would like the user to be able to drag items on top of other divs- and this dropped item should "morph" into this div (hopefully by using append()). This specific div that the element is dropped onto implements sortable(), so where ever the dropped element is placed should be its specific position on this sortable list.
EXAMPLE: If the div contains a number of dropped elements; lets say 5 items, if another item is dropped in between the 2nd and 3rd items, it should be appended to this div in that position.
Secondly, any element that is appended to a sortable div should then have the ability of being dragged out of this sortable div (un-appended) and back onto the main area of the workspace (I have no clue of how to do this!) BUT it should still holds its ability of being sorted (list should still be sortable).
I am using jQuery + jQuery UI to complete this project and may use other javascript-based extensions if they can complete my desired outcome easily.
Type of implementation I have at the moment
This implementation is very unfinished.
$("div.layout.lo-content > div.content").droppable(
{
drop: function(e, ui)
{
$(ui.draggable).appendTo($(this));
if($(this).hasClass("ui-sortable"))
{
$("div.content").sortable('refresh');
}
}
});
^^ when doing sortable('refresh') it breaks the system with error:
Uncaught Error: cannot call methods on sortable prior to
initialization; attempted to call method 'refresh'
The sortable list which the item is dragged onto:
$("div.layout.lo-content > div.content").sortable(
{
opacity:0.7,
axis:'y',
start: function(e, ui)
{
$(this).children("div.ui-sortable-placeholder").css("height",$(ui.helper).css("height"));
}
});
You could try using AngularJS with ng-sortable.
It looks like it can do exactly what you have described.
From readme
as-sortable can be added to the root element.
as-sortable-item can be added in item element, and follows
ng-repeat.
Here is a DEMO
Instead of ui.draggable you can use only https://jqueryui.com/sortable/ with the configuration parameter for connected lists.
It allows you to drag drop between different lists and also sort items per list.
API: http://api.jqueryui.com/sortable/
I'm very new to JS and I'm having trouble getting this to work.
Here is my code
jQuery('ul.menu li').each(function() {
jQuery(this).removeClass('current-menu-item');
jQuery(this).removeClass('current_page_item');
});
jQuery(this).parents('li').addClass('current_page_item');
jQuery(this).parents('li').addClass('current-menu-item');
Now what this should be doing is remove the highlight from one link on a navigation menu, and highlighting the one thats been clicked (I have an AJAX implementation).
For some reason it isn't doing anything. I have a feeling it is due to 'this' is there another way of structuring this code so I can work out if the code is wrong, which I don't believe it to be, or because of 'this'?
EDIT:
Apologies, it seems I haven't given enough information. I'm using the Twenty Fourteen wordpress theme but I'm serving the pages with AJAX.
http://twentyfourteendemo.wordpress.com/
I have the code being applied globally (I have other code in the same place to toggle the navigation once clicked (on mobile) and that works fine)
I have the menu at the top (without any dropdowns, just links). I can't give a link as it's not external currently. Should my code be working to change this?
As a few people have commented "What is 'this'" I feel I've completely missed something.
You don't need loop each item to do a remove class one by one, this is more easy :
jQuery('ul.menu li').removeClass('current-menu-item').removeClass('current_page_item');
Or (it's the same) :
jQuery('ul.menu li').removeClass('current-menu-item current_page_item');
But I don't understand what is this 'this' :
jQuery(this).parents('li').addClass('current_page_item');
jQuery(this).parents('li').addClass('current-menu-item');
Do you mean :
jQuery('ul.menu li').addClass('current_page_item current-menu-item');
Or if you are on an event listener (like click, as #Daniel Sanchez feel on comment) you just need to do :
jQuery('ul.menu li').click(function(){
// Remove class on each item
jQuery('ul.menu li').removeClass('current-menu-item current_page_item');
// Add class for this one
jQuery(this).addClass('current_page_item current-menu-item');
})
It's not entirely clear what you are trying to do but the code can be simplified somewhat:
jQuery("ul.menu li a").click(function(){
jQuery('ul.menu li').removeClass('current-menu-item current_page_item');
jQuery(this).parent('li').addClass('current_page_item current-menu-item');
});
http://jsfiddle.net/re3hjzyf/
Yes, by replacing this with 'ul.menu li'.
So the code would be like this
jQuery('ul.menu li').each(function() {
jQuery('ul.menu li').removeClass('current-menu-item')
.removeClass('current_page_item');
});
// not sure what the following code is referencing too
// it is outside the bounds of .each() function.
jQuery(this).parents('li').addClass('current_page_item');
jQuery(this).parents('li').addClass('current-menu-item');
what is this
When working with JavaScript and many Object Oriented programming languages the this keyword is used to refer to the current context that the programmer is working with. You're currently referencing to the ul.menu li element so by using this you make a call to the element that is selected in the .each() function.
You can replace it by using the element selector that you used in the each() function.
jQuery('.current-menu-item').removeClass('current-menu-item');
jQuery('.current_page_item').removeClass('current_page_item');
Here I am making the assumption that only one item will ever have those classes as it would denote which menu item is currently selected. The best way to select it is then to search for the class you want to remove. (If those classes always go together, you could also remove both on the same line, although then you might want to consider whether you actually need both.
jQuery('ul.menu li').on("click", function() {
jQuery(this).addClass('current_page_item').addClass('current-menu-item');
}
You can only use "this" as an argument for the selector when "this" has a value (i.e : inside an each loop or inside on.
In this case I am using the on() function to apply the function which adds the class to any of the list items which gets clicked on.
Merging the two you would then end up with :
jQuery('ul.menu li').on("click", function() {
jQuery('.current-menu-item').removeClass('current-menu-item');
jQuery('.current_page_item').removeClass('current_page_item');
jQuery(this).addClass('current_page_item').addClass('current-menu-item');
}
How do you append an item being dragged to a target element on drop, using jQueryUI's draggables/dropables? It looks like the way jQuery UI works right now is it just moves the items around on the screen via absolute positioning. Unfortunately, this functionality makes form submissions useless, as you cannot get the positions of the values on submission.
Thanks in advance for any items/pointers!
If I understood correctly, you want the dragged element to be detached from it's current parent and be appended to the new one, right? You can use a helper to do the dragging (so the original element is not affected) and, upon drop, detach it and append it to the target (thanks #Oleg and #Brian for improving over my original answer).
$(myDraggable).draggable({
helper:"clone",
containment:"document"
});
$(myDroppable).droppable({
drop:function(event, ui) {
ui.draggable.detach().appendTo($(this));
}
});
Working example at jsFiddle