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.
Related
So I have two files. An app.component.ts file and an app.component.html file.
Below is an image example of what I want to achieve in my User Interface.
If you look at the photo, you'll see an action icon by the right displaying a nav box element.
I tried achieving something similar in my angular application and this is what I get any time I click on the action Icon:
All the nav boxes display on the UI when I click on the icon. This is because the nav element is inside a *ngFor loop.
Here is my code in the app.component.html file:
<div class="row" *ngFor="let picture of pictures">
<div class="cell">
<p>{{picture.name}}</p>
<p class="med-text meta space-text">{{picture.ticketid}}</p>
</div>
<div class="cell"><p class="meta">{{picture.email}}</p></div>
<div class="cell-photo"><p class="meta">{{picture.ticket_type}}</p></div>
<div class="cell-large">
<div class="toggle on">
<div class="toggle"></div>
</div>
</div>
<div class="small">
<div>
<div class="toggle-on" (click)="toggleActionNav()">
<div class="action"></div
</div>
<!--- nav-Element Starts ---->
<nav class="dropdown-list w-dropdown-list w--open" *ngIf ="actionNav">
<div>View Pictures</div>
<div >Edit Pictures</div>
</nav>
<!--- nav-Element Ends ---->
</div>
</div>
</div>
And here is the code on my app.component.ts file:
actionNav: boolean;
toggleActionNav() {
this.actionNav = !this.actionNav;
}
My question goes thus. How do I get the nav elements to display uniquely and not all displaying together at the same time, just like it is in the first photo?
All responses will be deeply appreciated. Thanks
You can, for example, add a showActionNav property to your picture object. Then you can do (click)="picture.showActionNav = !picture.showActionNav" to toggle it and *ngIf ="picture.showActionNav" to display it.
simplest answer would be just set flag,
for example, actionNavOpen in your object:
(click)="picture.actionNavOpen = !picture.actionNavOpen"
in navs ngIf do: *ngIf ="picture.actionNavOpen"
of course if you're heavily typed this will give you some errors.
so few tips what to do next:
toggling of this flag (actionNavOpen) should be via method
in this method you can also set all others flag in pictures to false
just remember you don't need to pre-set this flag to falsy - it's already falsy while you get this data from rest api
to remove type errors you should extend returning model (interface) from rest api with your model which has this particular flag (actionNavOpen)
if you could show the before and after image will help to understand the problem. Here the problem statement given , when clicking the icons overlap or design itself is overlapping ?
actionNav variable shouldn't be in component's scope. It should be part of picture object which you are using in the ngFor.
And, pass the picture object along with index to the toggleActionNav method to change the actionNav value.
Below is what you need.
<div class="row" *ngFor="let (picture, index) of pictures">
<div class="cell">
<p>{{picture.name}}</p>
<p class="med-text meta space-text">{{picture.ticketid}}</p>
</div>
<div class="cell">
<p class="meta">{{picture.email}}</p>
</div>
<div class="cell-photo">
<p class="meta">{{picture.ticket_type}}</p>
</div>
<div class="cell-large">
<div class="toggle on">
<div class="toggle"></div>
</div>
</div>
<div class="small">
<div>
<div class="toggle-on" (click)="toggleActionNav(picture, index)">
<div class="action"></div>
</div>
<!--- nav-Element Starts ---->
<nav class="dropdown-list w-dropdown-list w--open" *ngIf="picture.actionNav">
<div>View Pictures</div>
<div>Edit Pictures</div>
</nav>
<!--- nav-Element Ends ---->
</div>
</div>
</div>
And the toggle method needs to be like:
toggleActionNav(picture, index) {
//disable all the actionNavs to false
this.pictures.map(pictureObj => pictureObj.actionNav = false)
this.pictures[index] = true
}
I have a semantic-ui accordion. It is working properly. But when user reloads page it is opening the default index item as expected. What I want is to open the lastly active index after page refresh. I decide to use javascript document.cookie to keep last active item's index. My problem is that I cannot get the index of element inside onOpen event.
HTML :
<div class="ui styled accordion sticky">
<div class="item">
<div class="title active">
Users
</div>
<div class="content active">
List
</div>
</div>
<div class="item">
<div class="title active">
Items
</div>
<div class="content active">
List
</div>
</div>
</div>
JQ:
$('.ui.accordion').accordion({
onOpen: function (item) {
setCookie('acordionIndex',this.index);
}
}).accordion('open', getCookie('acordionIndex'));
I found this question This question but the advised solution is not working.
Note : my getCookie and setCookie functions are working properly.
I have solved by trying alternative options. Changed onOpen event to onOpening
$('.ui.accordion').accordion('open', getCookie('acordionIndex') * 1).accordion({
onOpening: function (item) {
setCookie('acordionIndex', this.index('.content') - 1, 2)
}
});
I need to rearrange the div order of an RSS. Each item has 3 divs. I will need to move the div with the class "itemDate" before the div with the class "itemTitle" (see markup below). Should I use the function .each(); is there a jQuery out of the box solution for this or do I need to write my own function?
<div id="RSS">
<div class="col-md-3 item">
<div class="itemTitle"></div>
<div class="itemDate"></div>
<div class="itemContent"></div>
</div>
<div class="col-md-3 item">
<div class="itemTitle"></div>
<div class="itemDate"></div>
<div class="itemContent"></div>
</div>
<div class="col-md-3 item">
<div class="itemTitle"></div>
<div class="itemDate"></div>
<div class="itemContent"></div>
</div>
</div>
There is a function in jQuery called prependTo, which moves a element to the beginning of a given target. Check it out the example below.
$('.itemDate').each(function(){
$(this).prependTo($(this).parent());
});
This code just move every itemDate into the beginning of every respective parent.
I have this HTML
<div id="main-container">
<div style="style-here" data-status="active" data-state="loaded">
<div style="style-here">
<div style="style-here" {{click_event}}></div>
</div>
</div>
<div style="style-here" data-status="active" data-state="unloaded">
<div style="style-here">
<div style="style-here" {{click_event}}></div>
</div>
</div>
<div style="style-here" data-status="inactive" data-state="unloaded">
<div style="style-here">
<div style="style-here" {{click_event}}></div>
</div>
</div>
</div>
On click on one of the elements that has {{click_event}} I want to search recursively till I can find an element that has data-status or data-state, and in the worst case when I meet the id from top to stop de search.
The HTML is made generated from another JS file and I can't change the way is made it. Is there a way with closest or parent from jQuery to search after data attribute?
Thank you.
No need for recursion, you can use closest():
$clickedElement.click(function() {
var $parent = $(this).closest('[data-status], [data-state], #main-container');
});
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/