Dealing with a sortable list on jQuery - javascript

I am using the "sortable" script (http://farhadi.ir/projects/html5sortable/) to have a sortable list of items on my web application. The sorting part works great. But now, I need to be able to ping back to my server to set the order when things change.
The way to capture that event is:
$('.sortable').sortable().bind('sortupdate', function() {
//Triggered when the user stopped sorting and the DOM position has changed.
});
How do I understand the new position in order to inform my server?
Since the lists are small, I thought of two approaches:
1 - Understand in which position the item was dragged, look at the position right below and send some sort of "insert" update function to my server to insert the new item in that position.
2 - Just go through all the items on the list, capture their IDs in order and send the new ID list to the server and have the server re-build the index based on that list.
I can handle the ruby code but I am a disaster with JS/Jquery.
So, if I go with option 1 - how do I identify the position of the new item and how do I identify which is the item right below it?
If I go with option 2 - how do I iterate on all li items in the exact order they are positioned (their DOM order) so that I can build this list and send it back to the server?

Read the ids of the lis when the update is fired
var ids = $(".sortable").find("li").map( function(txt, elem){
return elem.id
} ).get();
console.log(ids);

Related

Storing post display order in database

I am developing a web application which will have images displayed in a slider. It is important that I am able to modify the order that they are displayed in.
Currently, I have a column in the table of images called 'order', which must be set to ensure the ordering works correctly, but changing it requires changing every other, too, which becomes tricky when dealing with hundreds of records.
This table, as well as queries for modifying it, are in development, so it's completely fine to change the way I do this.
My questions are:
When I'm inserting a new row, how can I make sure it appears at the end of the list? Auto-Increment in SQL tends to leave gaps if you delete entries from the table. How do I make sure that the row is assigned an order 1 greater than the highest order in the table?
How do I reorder the table? Imagine that I use a drag and drop interface (or similar) to reorder one image, bringing it to the top, or a different part of the list. If I do that, I need to reset the numbering of every item, which is, again, inefficient when dealing with hundreds of rows.
How do I prevent two rows from having the same order at any given time? The UNIQUE flag on the column? Presumably if I set that flag, changing the order from, say, 8 in one row opens up another to use that number. Right?
Thank you for your time, and I hope this isn't too vague a question to be easily answered!
Query the table you are about to insert into to find the MAX id in the table. Then on your insert just do this +1.
When re-ordering, say you want to set image order 6 to order 3. You will want to update all rows from order 3 and onwards to order+1 then set the image to order 3.
UPDATE table SET id = id+1 WHERE id IN (SELECT * FROM table where id >= 3)
If you are using unique on the order column to re-order you will have to update the current value to a temp value such as 99999, then use method in 2. However method 2 should keep this table from receiving any duplicated values.
sidenote
You could on delete of a picture re-evaluate the ids to keep no gaps
UPDATE table SET id = id-1 WHERE id IN (SELECT * from TABLE WHERE id > 3)
Where 3 is the deleted id
It will be in the end of the list. Just use auto increment feature and do not set ID manually (like lastID + 1) and you'll never have described problem.
You can allow user to change order of the list and then just update all order cells (for each member of the list). Or you can use Ajax and exchange order value for two members every time user drag-and-drops.
Use one of approaches described in 2 and you'll never have this problem.

AngularJS fixed list with updating content

Im in need of some inspiration on how to solve the following:
I'm making an information monitor using AngularJS.
The monitor should list a maximum of 6 rows of information.
A new row will always be put on top of the others and pushed in from the top. If there are already 6 rows, the last row will be pushed out from the bottom.
A row may disappear from the list at any given time.
Visually, I would very much like it to be sort of scrolling, so when a new row is to be displayed, it will slide in from the top, and all the items will slide a row down.
I'm not sure how to implement the above. I've thought about ng-repeat, but I don't know how to move the items when an element appears or is deleted.
I hope somebody can give me some advice.
For add new item in top list, use a unshift method of javascript. For example:
var list = [0,1,2]
list.unshift(3)
// results [3,0,1,2]
remember, add and remove items in $scope of list for update her.
$scope.list = [1,2,3,4,5,6];
$scope.list.unshift(9); // [9,1,2,3,4,5,6];
$scope.list.pop(1); // [9,2,3,4,5,6];
In HTML, continue using ng-repeat normally
You're going to want to look at ngAnimate. It has built-in support for working with ng-repeat including animations on the addition and deletion of items from a list.
https://docs.angularjs.org/api/ngAnimate
The docs for the integrations with ngRepeat are here: https://docs.angularjs.org/api/ng/directive/ngRepeat#animations

Highlight last inserted document in Meteor

I have form and list of objects at the same page. When I insert a new row, it is not very easy to see where the newly inserted row is placed. Therefore, I thought I could color/highlight the newly inserted row (and perhaps remove the highlight after a few seconds).
How can I do this? I think a way to do this could be using a method on the server which returns the inserted id (return Collection.insert(doc);) and on the client use a callback with
Meteor.call('insertDoc', function(err,result) {
// do something with result
});
I think I can use a reactive-var to save the id of the last inserted row and in the loop highlight the row with
{{#each docs}}
<li class="{{isActive}}">{{name}}</li>
{{/each}}
and have a helper to return active if this._id equals the reactive var with the last inserted id.
But is this the best way to do it? How can I remove the color after some seconds? I have seen such behaviour on many pages but I cannot find any tutorials/code snippets to achieve this.
I wrote a package that uses Meteor's UI hooks to fade items in and out of a list as they are added and removed, to help users maintain context as data changes:
https://github.com/mizzao/meteor-animated-each
There is a demo at http://animated-each.meteor.com/. You can see that as items are added and removed, they are faded in and out. If items are inserted off the screen, the visible area does not scroll.
This isn't doing exactly what you want, but you can use the same idea to highlight items as they appear as well, as opposed to the simple fade in.
Note that all of this happens at the UI rendering level - not the template/code level. The UI hooks are also not well documented right now, but they've been around for a while.
I don't know if your method is the best, but that's how I'd go about doing it.
As for the animation, I'd use a CSS3 animation. Plenty to choose from ( https://developer.mozilla.org/en-US/docs/Web/CSS/animation ), and you can easily make them fade to the standard color. The animation would also only be applied to the last inserted item (because of the way you did it, only the last item would have the "active" class)

AngularJS : how to sort in acsending / decending order

I am implementing the table view .In table view I am implementing infinite scroll .In other word I have 2000 objects .I am showing 25 element at one time .When user scroll to bottom it load more 25 elements so on .. I have "V" or "^" button on header .On click of this image I want to display in descending order only last 25 elements .when scroll more it load more data so on ..So I added filter in that but it is not working ..could you please tell me how we can implement this ..
I will give you example :Like A, B,D,C,K,N....T,Z objects when application load object is load like that .when user click it show Z,y,X ,W,V,U...A or again ascending way "A,B,C...Z"
here is plunker
$scope.setSort = function(idx, reverse){
$scope.sortval = 'columns['+idx+'].value';
$scope.reverse = reverse;
};
Html
<div class="col col-center brd gray-20" ng-repeat="d in invoice_column_name | filter:{checked: true}">
<sort-header label="{{d.label}}" index="{{d.index}}" sort-exp="setSort(idx, reverse)"></sort-header>
EDIT
Update
I will explain again I have 2000 objects ..It is display randomly .I am display only 25 object at one time .When user scroll more data it show again 25 data..But I want to sort that data in ascending as well as descending way .First I need to sort the 2000 objects then display 25 elements from that and than if user want to load more it scroll data and load that.In your example it is sorting first 25 object only .then load another 25 elements then sort 5o elements ..so on ..so it is not correct solution –
Update plunker
If you are dealing with a large collection of data, then it might be better to load the whole collection first. I have a couple of reasons for this:
Sorting the results on each load operation can be taxing for older browsers, especially as more data is brought in. This will slow down your UI.
If the data is not provided in order by the source, then the process of sorting might scatter the last-loaded set of items over several "pages" of the view before the one that your user is looking at. They will then have to search backwards through the results for the new information.
Try with with this library https://github.com/sroze/ngInfiniteScroll
First you need to load data from server or whatever you like, than in your controller you have to implement one function that gets called when user scrolls down. Also you can order your data in your controller
$filter('orderBy')(data, orderProp, desc/asc)
see angularjs filter order by. When user clicks on letter you have to order your data and search for first element in the array that starts with that letter. All you have to do next is to implement this in the ngInfinitScroll directive callback function.

How to list the items of a sortable grid-list in jQuery?

I am currently playing with the sortable interactions in jQuery. As for now, I added an unsorted list which is being displayed as a grid to my project. The source code is equivalent to the one I found in the jQuery demo section. I want the users to be able to display some values of a database, let them move each item to a position of their choice and send the changes back to the server. I implemented pretty much everything to do so, I however don't know how to obtain a list of the items on the client side, after users sorted the list according to their needs.
My question is: How can I get an array of all items after the user has moved the items around? I attempted to access the list's source code using something like this:
$( "#sortable" ).toArray()[0]
Which returns a HTMLUListElement object. The field innerText is undefined and innerHTML returns the source code of the entire unsorted list, I however would like to iterate through all the items of this list.
There has to be an easier way to access them. Any help would be appreciated.
$('#sortable li')
returns all the elements in your sortable.
If you want to display the values of them you can use
$('#sortable li').text()
which will print out all the text values of all the nodes in the right(sorted) order.
To access each of them separately you can use
$('#sortable li').eq(index)
or
$('#sortable li')[index]
It looks like this is what you need:
$("#sortable").sortable( "toArray" )[0]
http://jqueryui.com/demos/sortable/#display-grid
$(#sortable) gets you the tag that is sortable, .sortable gets you access to the sortable methods.

Categories

Resources