How to create a pagination and sorting using jquery? - javascript

I need to create a pagination using jquery which displays 5 results per page. Also I must allow the user to sort the results by price.
I created the pagination and it works fine. The bug is in the sorting function. When the user sorts the results it just sorts the results available in the specific page and not the total results. Here is the demo
The below is the function to sort the price.
var ascending = false;
$('.sortc').on('click', '.sortp', function (e) {
e.preventDefault();
var sorted = $('ul .price_indiv').sort(function (a, b) {
return (ascending == (convertToNumber($(a).find('.final_price').html()) < convertToNumber($(b).find('.final_price').html()))) ? 1 : -1;
});
ascending = ascending ? false : true;
$('.price').html(sorted);
});
var convertToNumber = function (value) {
return parseFloat(value.replace('$', ''));
}
Can someone help me to fix this bug? NOTE: Without a plugin

I think you have misunderstood how the Pager works.You may need to re-evaluate how this script works. It displays the proper items and simply hides the rest of the list items using display:none;
Before Sort
!
After Sort
!
So as DarkHorse said sorting is working perfectly. All you need to do is just may be reapply sorting function to get it work

Related

Javascript sort list works only onve

I'm trying to implement a question like system.
The questions should reorder with every like based on the data attribute 'vote'.
So every time a like event is received from the sockets the sort function gets called.
The first time a question gets liked everything works fine and the list is sorted.
But then it stops sorting. I already checked the data values.
Here is my js function:
function sortQuestionList() {
$('#questionList li').sort(sort_li).appendTo('#questionList');
function sort_li(a, b) {
return ($(b).data('vote')) < ($(a).data('vote')) ? -1 : 1;
}
}
Your sort_li function doesn't return the values sort expects. It should return:
A negative number if a comes before b
A positive number if b comes before a
Zero if they're the same
Your code isn't doing that last thing. This makes sort unable to do its job correctly.
Instead:
function sortQuestionList() {
$("#questionList li").sort(sort_li).appendTo("#questionList");
function sort_li(a, b) {
return $(a).data("vote") - $(b).data("vote"); // ***
}
}
(That assumes that the value of vote is numeric.)
Your sort function works. However, it is not stable. You should write
function sort_li(a, b) {
return $(b).data("vote") - $(a).data("vote");
}
Anyways, this is not your problem.
I made an example here and its working just fine: https://codesandbox.io/s/sort-questions-stackoverlow-49hvi?file=/src/index.js
The code you provided is not the root of your problem.
We cannot provide any further help without a non working example. Please make a minimal pen or codesandbox.
All I can say is: Make sure you call the sort function everytime you update the list items. Make sure no other function overwrites those changes. Make sure you use the right properties ('data-votes' instead of 'votes').

Sorting a HTML structure

Im trying to sort a div structure based on a paramter using a small javscript i found.
It seems to not perform exactly as expected. I understand the sorting function is not parsing the values perfectly...
This is the sorting logic is use...
<script type="text/javascript">
// Sorting Logic
$(function() {
$("a[href*=#]").click(function(e) {
e.preventDefault();
var liContents = [];
$('#ProductPrice span[id*="ABSPrice"]').each(function() {
liContents.push($(this).html());
});
liContents.sort(numOrdDesc);
$('#ProductPrice span[id*="ABSPrice"]').each(function() {
$(this).html(liContents.pop());
});
});
});
function numOrdDesc(a, b) {
return (parseInt(b) - parseInt(a));
}
// End
of Sorting Logic
Since i cannot exactly post the html i am going to add a link to the actual website where you can see this is action. Can anyone point out where i am going wrong?
http://www.absbiz.co.uk/Products/tabid/85/rvdsfcatid/Modems-437/Default.aspx
EDIT: Currently i think the sort is working, however i still cannot move the individual products. Only the prices get sorted and changed....
I took at look at your live site and injected the sorting function you used in your question. I noticed a few things. Firstly, the strings you are passing into your compare function look like this:
"£38.89 ex. VAT"
"£19.93 ex. VAT"
"£44.44 ex. VAT"
...
So parseInt("£38.89 ex. VAT") will return NaN. No compare. We can adjust this to remove all non-decimal information, and also parse a float instead, like so:
parseFloat("£38.89 ex. VAT".replace(/[^0-9\.]/g, "")); // --> 38.89
However, this will sort the above price strings, but we don't have association information on the products to properly sort them in the DOM (yet). For that we need to adjust what you put into your array.
The strategy is to find all the top item containers using $('.ProductListProductItem') and push their html into an array. Sort the array such that the prices are found by $('#ProductPrice span[id*="ABSPrice"]') and stripped of non-decimal information. Each top item container is then repopulated with the html from the sorted array.
Essential code:
var liContents = [];
// Push in all the product containers' innerHTML
$('.ProductListProductItem').each(function () {
liContents.push($(this).html());
});
// Use our new sorting routine
liContents.sort(numOrdDesc);
// Replace the html of each top item container
$('.ProductListProductItem').each(function () {
$(this).html(liContents.pop());
});
// Pass in jQuery elements, not strings
function numOrdDesc($a, $b) {
// Get the price further down in the DOM
var a = $('#ProductPrice span[id*="ABSPrice"]', $a).text();
var b = $('#ProductPrice span[id*="ABSPrice"]', $b).text();
return parseFloat(b.replace(/[^0-9\.]/g, "")) - parseFloat(a.replace(/[^0-9\.]/g, ""));
}
To verify this works, navigate to your live site and open DevTool > Console. Copy the above script and paste it into Console. Hit return, and note that the products are now sorted in ascending order. Enjoy.
Before:
After:
Your parseInt fails because of the pound sign. I'm guessing you want to strip that out in your sort function, and also use parseFloat instead since your prices are floating point numbers.
Try
function numOrdDesc(a, b) {
return parseFloat(b.replace(/[^0-9\.]/g, "")) - parseFloat(a.replace(/[^0-9\.]/g, ""))
}
The replace pretty much removes everything that's not a digit or a dot from the string before attempting to parse it
// "£298.73".replace(/[^0-9\.]/g, "") -> "298.73"
// parseFloat("298.73") -> 298.73
You are missing parameters to the function, you can do it like this.
liContents.sort(function(b, a) {
return (parseInt(b) - parseInt(a));
});

Filtering large list with javascript

I have a very large list of elements (14000+), I want to have a search field that as you type text into it, it filters the results and hides unrelated elements.
Currently I'm using this:
$.expr[':'].containsIgnoreCase = function (n, i, m) {
return jQuery(n).text().toUpperCase().indexOf(m[3].toUpperCase()) >= 0;
};
$("#search").on("keyup", function () {
var filter = $("#search").val();
$(".list-group-item").not(":containsIgnoreCase('" + filter + "')").addClass("hidden");
$(".list-group-item:containsIgnoreCase('" + filter + "')").removeClass("hidden");
});
Which works wonderfully...on smaller lists. This list is simply too large to be manageable with that code.
I don't know if there is any other code that can handle this many elements client side. If not, would it be better to leave the list blank, and do an ajax request to populate the list as matches are made?
I think there are many possible ways to optimize the search but whether you decide to use the code as shown in the question or use ajax calls I would suggest as an improvement to reduce the number of calls to the search function by using throttle / debounce. This will prevent the search to be called after each key stroke but instead will delay search execution with a number of milliseconds after the last key stroke. For example the code above can be changed as follows:
function searchFunction () {
var filter = $("#search").val();
$(".list-group-item").not(":containsIgnoreCase('" + filter + "')").addClass("hidden");
$(".list-group-item:containsIgnoreCase('" + filter + "')").removeClass("hidden");
}
$("#search").on("keyup", $.debounce(searchFunction, 300));
There are many open source implementations of debounce function over the net, but in the above example I have used jquery-debounced. In order to see how this works please check this jsfiddle. Another implementation is available in underscore.js library. Also I found a nice article on this subject.

Check all values in an array are same

I have a webpage that has a textbox.
When the user enters information into it, it makes a AJAX call to see if the entry is valid, if not it disables a button.
They can also add up to 10 textboxes which is done via jQuery Templates. At the moment each textbox has a class of serial and when a serial textbox is blurred it does this check.
If they enter a invalid serial it will disable the button but if they add a new textbox and that is valid the button is now enabled which is wrong as there is one still invalid.
The only way I can think to do this is to add a 1 or 0 to an array for each textbox and once all elements in the array are 1 then enable the button. Is that a good approach, if not please explain a better one. If it is a good approach how do I check all values in a javascript array are the same?
Thanks
This sounds like a good approach. You can check for equal elements in a javascript array using this simple javascript function. You may paste this to a firebug console to check its functionality.
// check if all elements of my_array are equal, my_array needs to be an array
function check_for_equal_array_elements(my_array){
if (my_array.length == 1 || my_array.length == 0) {
return true;
}
for (i=0;i<my_array.length;i++){
if (i > 0 && my_array[i] != my_array[i-1]) {
return false;
}
}
return true;
}
//Example:
var my_array = [];
my_array.push(5);
my_array.push(5);
// will alert "true"
alert("all elements equal? "+check_for_equal_array_elements(my_array));
my_array.push(6);
// will alert "false"
alert("all elements equal? "+check_for_equal_array_elements(my_array));
I will assume you have a isValid(str) function that returns a boolean.
Since you're using jQuery, you can take advantage of jQuery's filter() function to easily check if any inputs are invalid whenever an input blurs:
$('.serial').live('blur', function () {
// Get an array of all invalid inputs
var invalids = $('.serial').filter(function () {
return !isValid($(this).val());
});
// Does the array contain anything?
$('#button').prop('disabled', invalids.length);
});
Demo: http://jsfiddle.net/3RNV6/
Similar concept, but for use with AJAX:
$('.serial').live('blur', function () {
var me = this;
$.ajax({
// ajax config
success: function (data) {
if (data === 'Y') $(me).addClass('valid');
// Get an array of all invalid inputs
var invalids = $('.serial').filter(function () {
return !$(this).hasClass('valid');
});
// Enable if none invalid
if (invalids.length === 0) $('#button').prop('disabled', false);
}
});
});
$('.serial').live('keypress', function () {
$('#button').prop('disabled', true);
$(this).removeClass('valid');
});
First of if you dynamically create n textboxes you should use live() or delegate() methods of jQuery to inform of new DOM elements added.
Secondly your approach is just fine but instead of an array you can set param of inputs with wrong text and then disable button if there are any elements with wrong text. I think it will be faster than looping though all textboxes all over.
I would use validation to achieve this.
http://docs.jquery.com/Plugins/Validation#Demos
If you can validate client-side great - either use one of the existing jQuery validation functions shown in the link above, or write your own.
If you must validate server side via ajax, then you could build this into a custom validation routine.
Then in the call that shows/hides the button - make a call to $('#formid).validate() - returns false if any validation fails.

How to get jQuery Tablesorter to sort descending by default?

I can't figure this out. This question was also asked here http://www.nabble.com/TableSorter-plugin---default-column-sort-DESC-instead--How--to25180761s27240.html#a25180761 with no response.
I've tried
$.tablesorter.defaults.sortInitialOrder = 'desc';
and altering the jquery.tablesorter.js file to default to 'desc' but it doesn't work. When I click on the column headers, the first sort is still ascending so the user has to click twice to descend the values.
How can I get Tablesorter to sort by descending by default?
Try the latest version from the tablesorter site - this seems to be fixed somewhere between version 2.0.3 and 2.0.5.
<script type="text/javascript">
$(document).ready(function()
{
$("#theTable").tablesorter({
sortInitialOrder: 'desc',
sortList: [[3,1]] // etc.
});
}
);
</script>
...that worked with the latest version of tablesorter, but didn't with the previous one I had. Hope it helps!
Looks like a bug in the tablesorter code, or I'm misunderstanding what the sortInitialOrder parameter is supposed to do. At line 536 it sets the sorter order by looking at the number of times the column has been sorted and taking the value mod 2. It should also take into account the value of sortInitialOrder.
Change line 536 from
this.order = this.count++ % 2;
to
this.order = this.count++ == 0 ? this.order : (1 - this.order);
And add after this line (so that the first click on a different column gives you the default)
$headers.not($cell).each( function() {
this.count = 0;
});
and change line 421 from
o.count = s[1];
to
o.order = o.count = s[1];
so that the initial order is overridden if a sortList is applied.
Then you can use the sortInitialOrder parameter to tablesorter to set up a default first sort order for the column. Any ordering provided in the sortList will override the sortInitialOrder provided for the entire table.
Note that this applies to Tablesorter 2.0.
Simply use this, second item in array is sort order (0 = ascending, 1 = descending):
.tablesorter({ sortList: [[0, 1]] });

Categories

Resources