jquery ui draggable scrolling within container - javascript

I have an unordered list and have added draggable functionality to each of the list item using jquery ui draggable. the list is inside a div with id="content". Here is the snapshot of my UL list
Here is the code i have written:
<script src="../../jquery-1.8.0.js"></script>
<script src="../../ui/jquery.ui.core.js"></script>
<script src="../../ui/jquery.ui.widget.js"></script>
<script src="../../ui/jquery.ui.mouse.js"></script>
<script src="../../ui/jquery.ui.draggable.js"></script>
<script type="text/javascript">
$(function() {
$( ".draggable" ).draggable({
scroll: true,
scrollSensitivity: 100,
revert: true,
containment: '#content',
zIndex: 999990,
revertDuration: 100,
delay: 100
});
});
</script>
<div style="width:200px;height:300px;overflow:auto;" id="content">
<ul>
<li class="draggable">One</li>
<li class="draggable">Two</li>
<li class="draggable">Three</li>
<li class="draggable">Four</li>
<li class="draggable">five</li>
<li class="draggable">six</li>
<li class="draggable">Seven</li>
<li class="draggable">Eight</li>
<li class="draggable">Nine</li>
<li class="draggable">Ten</li>
<li class="draggable">Eleven</li>
<li class="draggable">Twelve</li>
<li class="draggable">Thirteen</li>
<li class="draggable">Fourteen</li>
<li class="draggable">Fifteen</li>
<li class="draggable">Sixteen</li>
<li class="draggable">Seventeen</li>
<li class="draggable">Eighteen</li>
<li class="draggable">Nineteen</li>
<li class="draggable">Twenty</li>
</ul>
</div>
What I would like to do is when I am dragging any list item within the container (i.e div with id="content") and when the mouse is at the edge of the div border or size, the container should also scroll so that i could move upward and downward within the container.
For example if i wanted drag the last list item in the list to the first in the list, so when the mouse is at the top end of the div edge, the container (in our case div) should also scroll automatically. Is this a bug in jquery ui draggable?
Please help

Try downgrading to jQuery 1.7.2
(Its not supposed to work with 1.8 yet I think. You can find the latest compatible version within the rar when you download jQuery UI)

Related

Only make button clickable when something is done

I want a button that can only be pressed when all the options from 1 box are moved to the other box.
see screenshot of the interface are here:
interface
so all the options from the blue box are dragged in the green box and then the button becomes active. is this possible?
my code:
$(document).ready(function(){
$('.next').click(function() {
$('.current').removeClass('current').hide()
.next().show().addClass('current');
if ($('.current').hasClass('last')) {
$('#next').attr('disabled', true);
}
$('#prev').attr('disabled', null);
});
});
$(document).ready(function(){
$( function() {
$( "#sortable1, #sortable2" ).sortable({
connectWith: ".connectedSortable, .connectedSortable1"
}).disableSelection();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.css" rel="stylesheet"/>
<div id='div2' class='dropboxes'>
<!--box with options to drag to the other box-->
<ul id="sortable1" class="connectedSortable">
<li class="ui-state-default" style="cursor:move;" id='I'>option1</li>
<li class="ui-state-default" style="cursor:move;" id='D'>option2</li>
<li class="ui-state-default" style="cursor:move;" id='C'>option3</li>
<li class="ui-state-default" style="cursor:move;" id='S'>option4</li>
</ul>
<!--other box where the options above can be dropped-->
<ul id="sortable2" class="connectedSortable1">
</ul>
<!--this button has to be only clickable when all the options are dragged to the other box-->
<button class="next">Volgende</button>
</div>
How can I do this ?
You can achieve this using .drop event of sortable. Please check snippet for more understanding.
$(document).ready(function(){
$('.next').click(function() {
$('.current').removeClass('current').hide()
.next().show().addClass('current');
if ($('.current').hasClass('last')) {
$('#next').attr('disabled', true);
}
$('#prev').attr('disabled', null);
});
});
$(document).ready(function(){
$( function() {
$( "#sortable1, #sortable2" ).sortable({
connectWith: ".connectedSortable, .connectedSortable1",
stop: function( ) {
if($("#sortable1 li").length > 0){
$(".next").prop("disabled",true);
}else{
$(".next").prop("disabled",false);
}
}
}).disableSelection();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.css" rel="stylesheet"/>
<div id='div2' class='dropboxes'>
<!--box with options to drag to the other box-->
<ul id="sortable1" class="connectedSortable">
<li class="ui-state-default" style="cursor:move;" id='I'>option1</li>
<li class="ui-state-default" style="cursor:move;" id='D'>option2</li>
<li class="ui-state-default" style="cursor:move;" id='C'>option3</li>
<li class="ui-state-default" style="cursor:move;" id='S'>option4</li>
</ul>
<!--other box where the options above can be dropped-->
<ul id="sortable2" class="connectedSortable1">
Drag Here
</ul>
<!--this button has to be only clickable when all the options are dragged to the other box-->
<button disabled="disabled" class="next">Volgende</button>
</div>
Buttons can be disabled and enabled with their HTML disabled attribute
<button id="nextBtn" disabled="true">Disabled</button>
With access to DOM events and the moveable items you can check when objects are dragged over. When all have been moved then change the button's disabled attribute.
document.getElementById('nextBtn').disabled = false;
Here's is one of the possible way
If you have predefined number of options you could use counter provided you should make sure that the same option doesn't get clicked twice ,and then in the button click function check the counter value.
eg. 5 options counter value should be 5
if counter == 5
perform button click
It's possible by using the contentChanged event listener. Since you are using jQuery already, this might help.
$('#sortable2').on('contentChanged', function(){
if($(this).children().length == 4)
$('.next').attr('disabled', false);
});
This code is checking if the contents on the right hand list has changed and if so, we are checking if the number of list items present are 4 and enabling the button by setting it's attribute disabled to false. If you don't know the number of items on the left hand side, pre calculate and pass it to the call back while checking items on the right side.

Not able to drag appended items

I'm trying to make an appended item draggable using jquery ui, With jquery I'm trying to say when a veggie is clicked add it to the dirt.
make the veggies draggable in the dirt but be constrained within that element. Is there a reason the following code isn't working?
<body>
<ul id = "dirt">
</ul>
<ul id = "veggies">
<li class ="veg tomato"></li>
<li class ="veg cucumber"></li>
<li class ="veg pepper"></li>
<li class ="veg eggplant"></li>
<li class ="veg beans"></li>
</ul>
<script>
$(document).ready(function(){
$("#veggies li").click(function(){
$(this).clone().appendTo("#dirt");
});
$("#dirt li").draggable({
containment: '#dirt'
});
});
</body>
You need to make the element draggable AFTER you append it, as shown in this fiddle: https://jsfiddle.net/5b3nfm11/1/
$(document).ready(function(){
$("#veggies li").click(function(){
$(this).clone().appendTo("#dirt").draggable({
containment: '#dirt'
});
});
});
It looks like you should be making your #veggies list items draggable instead of appending them on click.
This ought to work.
$(document).ready(function(){
$("#veggies li").draggable(function(){
$(this).clone().appendTo("#dirt")
});
});

Change the background of li element using the html content of that element

Im pretty sure this is possible, I think Im on the right track, yet it still isn't working for me;
I have this as the jquery, have imported the latest jquery file - what I want is for each colour list item, the content that they contain will be used as their background colour.
If anyone can help me, as I have tried for tens of hours with no success, thank you.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
$( "$li.selected-color" ).each(function(element) { var colorlinkcontent = $(element).html(); $(element).css("background-color", colorlinkcontent); });
</script>
<ul class="colors">
<li class="selected-color">#f334568
<li class="selected-color">#f334568
<li class="selected-color">#f334568
<li class="selected-color">#f334568
</ul>
<hr/>
<span class="title">Selected criteria:</span>
<ul class="selected-criteria">
<li>yolo
<li class="selected-color">#f334568
<li>Website
</ul>
Some issues:
No li closing tags.
No script opening tag.
The hex colour codes have too many digits.
The script tag needs to wait until the DOM is loaded or go after the list elements.
You need to read how .each() works as the first argument of the callback function is the index not the element.
The selector should be li.selected-color rather than $li.selected-color.
<ul class="colors">
<li class="selected-color">#f33456</li>
<li class="selected-color">#f33456</li>
<li class="selected-color">#f33456</li>
<li class="selected-color">#f33456</li>
</ul>
<hr/>
<span class="title">Selected criteria:</span>
<ul class="selected-criteria">
<li>yolo</li>
<li class="selected-color">#f33456</li>
<li>Website</li>
</ul>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script>
$( "li.selected-color" ).each( function() {
var $el = $(this);
$el.css( "background-color", $el.text() );
});
</script>

Access newly created DOM elements for looping

I'm using jQuery sortable + jQuery draggable to put together a page that adds and removes images to a slideshow. I have it set up now such that I can drag in new screens and drop them into the named sequences I want, and it'll create the DOM elements I need.
I am successfully scanning the page for the necessary elements and committing them to an array, but it never picks up the newly added items. So for example, I have the following elements to begin with:
<h3 data-sequence-title="sequence1">Sequence 1</h3>
<ul class="sortable connectedSortable ui-sortable">
<li data-screen="screen1">Screen 1</li>
<li data-screen="screen2">Screen 2</li>
<li data-screen="screen3">Screen 3</li>
</ul>
...and I then add a row:
<h3 data-sequence-title="sequence1">Sequence 1</h3>
<ul class="sortable connectedSortable ui-sortable">
<li data-screen="screen1">Screen 1</li>
<li data-screen="screen2">Screen 2</li>
<li data-screen="screen3">Screen 3</li>
<li data-screen="screen4">Screen 4</li>
</ul>
jQuery will only ever return the first elements, not the updated ones. Here's the js I'm using:
$( document.body ).on('click', '.submit', function(){
// Build nested array from DOM elements
var jsonObj = [];
$('.sortable').prev('h3').each(function(){
var obj = {
title: $(this).data("sequence-title"),
Screens: []
};
$(this).next("ul").children('li').each(function() {
obj.Screens.push({
image: $(this).data("screen")
});
});
jsonObj.push(obj);
});
});
Code that adds new LIs:
// Initialize draggable / droppable functionality
$('.sortable').sortable({
placeholder: 'ui-state-highlight',
revert: true
});
$('.draggable li').draggable({
connectToSortable: '.sortable',
helper: 'clone',
revert: 'invalid'
});
$('.sortable').disableSelection();
I need to return the modified DOM, not the elements that were there when I loaded the page.
After you add an element to your sortable you have to update the component:
$(".sortable").sortable("refresh");
I did a quick experiment based on your code. I am able to drag elements from below and add them to the first sequence. Then they are accessible when the clicky button is clicked.
<html>
<head>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script type="text/javascript" src="js/jquery-ui-1.10.3.custom.min.js"></script>
</head>
<body>
<div id="moo">clicky</div>
<ul class="sortable connectedSortable ui-sortable">
<h3 data-sequence-title="sequence1">Sequence 1</h3>
<li data-screen="s1screen1">Seq 1 Screen 1</li>
<li data-screen="s1screen2">Seq 1 Screen 2</li>
<li data-screen="s1screen3">Seq 1 Screen 3</li>
</ul>
<ul class="draggable">
<h3 data-sequence-title="sequence2">Dragable Sequence (Drag these elements up and assign to sequence 1)</h3>
<li data-screen="s2screen1">Seq 2 Screen 1</li>
<li data-screen="s2screen2">Seq 2 Screen 2</li>
<li data-screen="s2screen3">Seq 2 Screen 3</li>
</ul>
<script>
$(document.getElementById('moo')).on('click', function(){
// Build nested array from DOM elements
var jsonObj = [];
$('.sortable h3').each(function(){
var obj = {
title: $(this).data("sequence-title"),
Screens: []
};
$(this).siblings("li").each(function() {
obj.Screens.push({
image: $(this).data("screen")
});
});
jsonObj.push(obj);
});
alert(JSON.stringify(jsonObj));
});
// Initialize draggable / droppable functionality
$('.sortable').sortable({
placeholder: 'ui-state-highlight',
revert: true
});
$('.draggable li').draggable({
connectToSortable: '.sortable',
helper: 'clone',
revert: 'invalid'
});
$('.sortable').disableSelection();
</script>
</body>
</html>

Filter jQuery sortable items

I have two div containers that are sortable and connected with connectWith. In both there are sortable items that I can drag and drop as intended. These items have some classes, for example, group1 and group2. Let's call containers container1 and container2. I need to make possible group1 items to be dragged and dropped into any of containers and group2 items to be dragged and dropped only inside container2. I have read jQuery docs but didn't find an answer or an idea how to do this.
Try subscribing to the receive event. I haven't tested this, but my guess is that if you return false (the standard pattern for blocking events in jQuery), the items dropped won't be added to a list. Here's some pseudo-code to get you started...
$("...").sortable(
{
receive: function ()
{
// assuming that "this" maps to the current object being dragged
if (this.className.indexOf("...")) return false;
}
});
EDIT I've come up with a solution that better answer your needs. This code can be tweaked a bit for example to make the items with group2 NOT sortable at all, even if they already are in container1.
JS:
$(function() {
$(".container1,.container2").sortable();
// on mousedown set the "connectWith" option of sortable depending on
// whenever item that user may start dragging has class "group1" or not
$(".container1 > li, .container2 > li").mousedown(function() {
var $this = $(this);
$this.parent().sortable("option", "connectWith", $this.hasClass('group1') ? '.connectedSortable' : false);
})
});
HTML:
<ul class="container1 connectedSortable">
<li class="group1">item 1.1</li>
<li class="group2">item 1.2</li>
<li class="group1">item 1.3</li>
<li class="group2">item 1.4</li>
</ul>
<ul class="container2 connectedSortable">
<li class="group1">item 2.1</li>
<li class="group2">item 2.2</li>
<li class="group2">item 2.3</li>
<li class="group1">item 2.4</li>
<li class="group2">item 2.5</li>
</ul>

Categories

Resources