Unfortunately, I am not able to get this working in jsfiddle but maybe I overlooked something (http://jsfiddle.net/bJpyU/46/). I have blocks dynamically created and need to save the order that they are placed. Because of the dynamic fashion that this is set up, I am not able to get the index (it's always 0, and the block starting first always shows as first index wise regardless of where it is dragged). toArray and serialize are showing up as blank. I've even tried counting nth-child. Any idea how to get the order?
HTML
<div class="tab-pane active col-lg-12" id="portlet_tab_Graphs">
<div class="row padLR sortable_portlets" id="sortable_portlet_Graphs">
<div class="col-lg-4 sortable sortable_portlet_Graphs_column ui-sortable" id="102">
<div class="portlet box yellow">
<div class="portlet-title">Monthly License Revenue</div>
</div>
<div class="portlet-body clearfix pad">
<div id="h1_sortable_portlet_Graphs_102"></div>
<div id="sortable_portlet_Graphs_102">
<div class="col-lg-12 nPad">
<div class="btn-group chartToggle inline">Graph Data</div>
</div>
</div>
</div>
</div>
<div class="col-lg-4 sortable sortable_portlet_Graphs_column ui-sortable" id="103">
<div class="portlet box blue">
<div class="portlet-title">Yearly License Revenue</div>
</div>
<div class="portlet-body clearfix pad">
<div id="h1_sortable_portlet_Graphs_102"></div>
<div id="sortable_portlet_Graphs_102">
<div class="col-lg-12 nPad">
<div class="btn-group chartToggle inline">Graph Data</div>
</div>
</div>
</div>
</div>
</div>
</div>
JQUERY
var sortdiv = "Graphs"
var blockClasses = "col-lg-4";
$(".sortable_portlet_" + sortdiv[2] + "_column").sortable({
connectWith: ".sortable_portlet_" + sortdiv[2] + "_column",
handle: ".portlet-title",
//placeholder: "dragColumn",
forceHelperSize: true,
forcePlaceholderSize: true,
start: function (e, ui) {
ui.placeholder.height(ui.helper.outerHeight());
ui.placeholder.width(ui.helper.outerWidth());
// get original block size
blockClasses = ui.item.parent().attr('class');
},
stop: function (e, ui) {
var parent = ui.item.parent();
blockWidth = blockClasses.split(" ");
parent.attr('class', function (i, c) {
return c.replace(/(^|\s)col-lg-\S+/g, blockWidth[0]);
});
//console.log(ui.position)
SavePortletDrop(sortdiv[2]);
}
});
I think the error is actually from attaching sortable to each individual item that you're sorting. It should be attached to a container div.
So, even though it looked like it was working, you were actually moving around a bunch of 1-item lists, which are always at index 0.
I got it to work like I think you want it by attaching sortable to the #sortable_portlet_Graphs. This makes ui.item.index() return the number you'd expect in the stop function.
http://jsfiddle.net/bJpyU/47/
Related
I'm creating an interface so users can drag and drop elements, but also sort them afterwards. The drag / drop / sort functions work smoothly, however, when I'm trying to sort the dropped elements in the "dropzone", instead of the element I'm trying to drag, it's the element source that is moving. It took some times but I figured out that it's because of .clone(true) or .clone(false) that this kind of things could happen. So I decided to remove it but now the elements that are in the sorting div seem.. broken.
Here is the HTML (bootstrap 4 context) :
<div class="row">
<div class="card col-3">
<div class="card-body">
<div class="card draggable-element" data-target="textarea">
<div class="card-body">
This is some text within a card body. 1
</div>
</div>
<div class="card draggable-element" data-target="textfield">
<div class="card-body">
This is some text within a card body. 2
</div>
</div>
<div class="card draggable-element" data-target="fileinput">
<div class="card-body">
This is some text within a card body. 3
</div>
</div>
</div>
</div>
<div class="card col-6 offset-1">
<div class="card-body dropzone">
</div>
</div>
</div>
And this is the JS :
$(document).ready(function() {
$('.draggable-element').draggable({
revert: 'invalid'
, appendTo: '.dropzone'
, helper: 'clone'
});
$('.dropzone').droppable({
drop: function(event, ui) {
var item = $(ui.draggable);
if (!item.hasClass('copy')) {
var newy = item.clone(true, true);
newy.addClass('copy');
//console.log(newy);
newy.draggable({
revert: 'invalid'
, stack: ".draggable"
});
} else {
$(this).append(item);
}
$('.dropzone').append(newy);
}
}).sortable({
axis: 'y'
, revert: true
, refreshPositions: true
, placeholder: 'placeholder'
, items: '.copy'
, forcePlaceholderSize: true
});
});
So with parameters inside .clone(), whichever they are, most of the time, when I drag a cloned element, the original is moving instead, but sometimes it works, and I have no clue why. Without parameters, the good element is dragged but there is no notion of stacking and sorting, the element stays where I dropped it and the others kind of adapt their position to its.
Is there anyway to resolve this kind of issue?
Thank you in advance
You don't need to droppable and sortable method is enough because it's draggable and sortable. So you can do it like this:
$('.dropzone').sortable();
$('.draggable-element').draggable({
connectToSortable: '.dropzone',
revert: 'invalid',
helper: 'clone'
});
Online demo (jsFiddle)
If you want move element "draggable-element", you must set as dragable "zone" card-body (higher tag). But this tag you are have twice in your html code.
Check my live example.
Live demo
<div class="row">
<div class="card col-3">
<div class="card-body">
<div class="card draggable-element" data-target="textarea">
<div class="card-body">
This is some text within a card body. 1
</div>
</div>
<div class="card draggable-element" data-target="textfield">
<div class="card-body">
This is some text within a card body. 2
</div>
</div>
<div class="card draggable-element" data-target="fileinput">
<div class="card-body">
This is some text within a card body. 3
</div>
</div>
</div>
</div>
</div>
<div class="card col-6 offset-1">
<div class="card-bodyX dropzone">
...
</div>
</div>
$(document).ready(function() {
$('.card-body').draggable({
revert: 'invalid',
connectToSortable: '.dropzone',
scroll: false,
helper: 'clone'
});
$('.dropzone').sortable({
distance: 0,
});
});
I want to hide panel-body if it is empty.
Here's the example: BootPly
Code Javascript:
$(function() {
$('#container').load(function() {
if($.trim($(this).contents().find("container").find('panel-body').length) == 0) {
$(this).hide();
}
});
Code HTML:
<div class="container">
<div class="row clearfix">
<div class="col-md-9 column">
<div class="panel panel-primary">
<div class="panel-heading">Content</div>
<div class="panel-body fixed-panel">
<div class="form-group">
</div>
</div>
</div>
</div>
</div>
</div>
How about something like this? http://www.bootply.com/bKb0isdzKA
$(function() {
$('.form-group').each(function() {
if ($(this).is(':empty')) {
$(this).closest('.container').hide();
}
});
});
You had a few issues. For one, you were using #container as your selector, despite container being a class. Additionally, you were checking to see if body-panel was empty, but it contained a child div, so it would always have HTML content.
The code above will loop through each .form-group and hide the parent container if it's empty.
If this isn't exactly what you had in mind, let me know and I can make adjustments.
This is an awkward problem, which will be better explained by looking at the live demo. Basically I have a news box populated with ng-repeat using Angular. Then I am using a jquery plugin called news ticker which allows the news headlines to move around. The first time you land on the page the news items are in their proper spots and they call the function accordingly. After moving them up or down, they stop calling the function, set a breakpoint in the code and after moving the breakpoint is never hit.
Edit - After researching this further I have found that it is because the elements need to be compiled using $compile after they're re added. However following some examples I have not gotten this to work. I need a way of compiling after a move event with this plugin.
Live demo
Angular Script for with function that should be called.
$scope.UpdateNews = function (item,number) {
console.log(item + ' ' + number);
switch (item)
{
case 'General':
$scope.NewsCast.General.Body = $scope.News.GeneralNews[number].Text;
break;
}
};
What the HTML looks like with the news boxes
<script src="http://www.jqueryscript.net/demo/Responsive-jQuery-News-Ticker-Plugin-with-Bootstrap-3-Bootstrap-News-Box/scripts/jquery.bootstrap.newsbox.min.js" type="text/javascript"></script>
<div class="row">
<div class="col-md-6 col-lg-3">
<div class="panel panel-default">
<div class="panel-heading"> <span class="glyphicon glyphicon-list-alt logo-inverse pull-left"></span><b> General News</b></div>
<div class="panel-body">
<div class="row">
<div class="col-xs-12">
<ul class="demo1" style="overflow-y: hidden; height: 280px;" ng-model="Idk">
<li style="" class="news-item text-left" ng-repeat="item in News.GeneralNews"><strong>{{item.DateValue | date: "MMM dd yyyy"}}</strong> {{item.Preview}}<a class="FakeClickable" ng-click="UpdateNews('General',item.index)" data-target="#GeneralModal" data-toggle="modal">Read more...</a></li>
</ul>
<div ng-if="Width>768">
<div ng-include="'../pages/Modals/General/GENERAL_INLINE.html'"></div>
</div>
</div>
</div>
</div>
<div class="panel-footer"> </div>
</div>
</div>
Have a tree structure like the following
Section 1
item1
item2
Section 2
item5
I can click on any item and hide all the other items with the dynatree onActivate function and this code
onActivate: function(node) {
var resultId = "#" + node.data.title;
resultId = resultId.replace(/\s/g, '');
$('#contents>div').not(resultId).hide();
$(resultId).show();
},
My html is this
<div class="container-fluid text-left">
<div class="row content">
<div class="col-sm-2 sidenav" id="tree"> </div>
<div class="col-sm-8" id="contents">
<div id="item1">
<table id="item1grid"></table>
</div>
<div id="item2">
<table id="item2grid"></table>
</div>
<div id="item5">
<table id="item5grid"></table>
</div>
</div>
<div id="info"> </div>
</div>
</div>
</div>
How can I extend this html and function so if I click "Section 1" in the tree it shows all the items in that section only i.e. clicking "Section 1" only shows item1 and item2
Maybe you can achieve this by using some properties of incoming node object of 'onActivate' callback. You need to check that activated object is a folder and if so, display all the chidlren of this element. Try to append this snippet inside of your onActivate callback:
if (node.data.isFolder) {
for (var i = 0; i < node.childList.length; i++) {
$('#' + node.childList[i].data.key).show();
}
}
Feel free to dump the entire object with console.log and check which fields you're able to use.
Could you please provide a jsfiddle to check what you're having so far?
I am using jQuery UI sortable for a list of elements on a page whose order I want to save in the database every time it’s changed.
However, I’m experiencing a weird bug (it seems to me like one): both the serialize and toArray methods always exclude one item from the produced serialised string (or array). That always is the item being currently dragged. Which means the order is never actually tracked properly.
Here’s an example of my javascript:
$('.setContent').sortable({change:
function(event, ui) {
// Serialise the new order
var newOrder = $('.setContent').sortable('serialize');
// Add the current set id and the action name
newOrder += '&setId='+currentSet+'&action=usrStuff:changeCardsOrder';
// Send the data to the server
$.post('ajax.php', newOrder);
}
});
And the HTML:
<div class="setContent>
<div class="cardSmall" id="card_5">
<div class="hanzi">俄国</div>
<div class="meaning">Russia</div>
</div>
<div class="cardSmall" id="card_4">
<div class="hanzi">韩国</div>
<div class="meaning">Korea</div>
</div>
<div class="cardSmall" id="card_6">
<div class="hanzi">中国</div>
<div class="meaning">China</div>
</div>
<div class="cardSmall" id="card_12">
<div class="hanzi">日本</div>
<div class="meaning">Japan</div>
</div>
<div class="cardSmall" id="card_13">
<div class="hanzi">德国</div>
<div class="meaning">Germany</div>
</div>
<div class="cardSmall" id="card_17">
<div class="hanzi">巴西</div>
<div class="meaning">Brasil</div>
</div>
<div class="cardSmall" id="card_14">
<div class="hanzi">法国</div>
<div class="meaning">France</div>
</div>
<div class="cardSmall" id="card_19">
<div class="hanzi">美国</div>
<div class="meaning">America</div>
</div>
<div class="cardSmall" id="card_16">
<div class="hanzi">英国</div>
<div class="meaning">England</div>
</div>
</div>
So, in this case, there are nine items in the list. But the sortable method will only return information about eight.
So how do I fix this?
You probably want the update event, not the change event.
change fires during sorting whenever the ordering of the items in the DOM changes, even if the user hasn't let go of the item they're moving. update fires after the user has changed the order of the sortable elements.