I an issue with sorting div elements by price values. The functionality of the code works OK but it seems that it doesn't quite sort the numbers correctly.
As you can see from my jsfiddle when the button is pressed the number 21.35 comes after numbers 102.35 and 200.
Can anyone shed some light on this?
Here is the html
<div class="wrap">
<button id="numBnt">Numerical</button>
<div id="container">
<div class="box">
<h2>10.35</h2>
</div>
<div class="box">
<h2>21.35</h2>
</div>
<div class="box">
<h2>21.35</h2>
</div>
<div class="box">
<h2>102.35</h2>
</div>
<div class="box">
<h2>10.35</h2>
</div>
<div class="box">
<h2>10.35</h2>
</div>
<div class="box">
<h2>10.95</h2>
</div>
<div class="box">
<h2>100.35</h2>
</div>
<div class="box">
<h2>100.05</h2>
</div>
<div class="box">
<h2>200</h2>
</div>
<div class="box">
<h2>5,510.25</h2>
</div>
</div>
</div>
And the javascript
var $divs = $("div.box");
$('#numBnt').on('click', function () {
var numericallyOrderedDivs = $divs.sort(function (a, b) {
return $(a).find("h2").text() > $(b).find("h2").text();
});
$("#container").html(numericallyOrderedDivs);
});
And here is the jsfiddle.
http://jsfiddle.net/C2heg/370/
The reason you're getting these results is that your sort is not numeric, it is based upon canonical values of the numbers.
The reason why 21.35 comes after number 102.35 is because the digit 1 in 102.35 is smaller than the digit 2 in 21.35 and 0 in 200 is smaller than 1 in 21.35.
Fix:
Parse to the numbers to float , before sorting
var numericallyOrderedDivs = $divs.sort(function (a, b) {
return parseFloat($(a).find("h2").text()) > parseFloat($(b).find("h2").text());
});
Updated fiddle
You need to parse to the numbers, use parseFloat.
You need to remove , from the text.
Code:
var numericallyOrderedDivs = $divs.sort(function (a, b) {
return parseFloat($(a).find("h2").text().replace(/,/g, '')) > parseFloat($(b).find("h2").text().replace(/,/g, ''));
});
jsfiddle Demo
Demo:
var $divs = $("div.box");
$('#numBnt').on('click', function() {
var numericallyOrderedDivs = $divs.sort(function(a, b) {
return parseFloat($(a).find("h2").text()) > parseFloat($(b).find("h2").text());
});
$("#container").html(numericallyOrderedDivs);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.0/jquery.min.js"></script>
<div class="wrap">
<button id="numBnt">Numerical</button>
<div id="container">
<div class="box">
<h2>10.35</h2>
</div>
<div class="box">
<h2>21.35</h2>
</div>
<div class="box">
<h2>21.35</h2>
</div>
<div class="box">
<h2>102.35</h2>
</div>
<div class="box">
<h2>10.35</h2>
</div>
<div class="box">
<h2>10.35</h2>
</div>
<div class="box">
<h2>10.95</h2>
</div>
<div class="box">
<h2>100.35</h2>
</div>
<div class="box">
<h2>100.05</h2>
</div>
<div class="box">
<h2>200</h2>
</div>
<div class="box">
<h2>5510.25</h2>
</div>
</div>
</div>
Related
<div class="my-attributes">
<div class="row">
<div class="SameClass"><strong>Condition</strong></div>
<div class="SameClass-value" itemprop="condition">New</div>
</div>
<div class="row">
<div class="SameClass"><strong>Color</strong></div>
<div class="SameClass-value" itemprop="color">Black</div>
</div>
<div class="row">
<div class="SameClass"><strong>Availability</strong></div>
<div class="SameClass-value" itemprop="avail">In Stock</div>
</div>
<div class="row">
<div class="SameClass"><strong>Quantity</strong></div>
**<div class="SameClass-value" itemprop="qty"> 5 </div>**
</div>
<div class="row">
<div class="SameClass"><strong>Price</strong></div>
<div class="SameClass-value" itemprop="price">250</div>
</div>
I have multiple divs that has the same class and 'itemprop' attribute and I need to be able to create a function that will return the Quantity (which in the example above is '5')
the catch here is that the structure you see above changes in other pages. In the example above, the Condition and the Color shows but on other pages those do not appear which means the structure changes except the class name and the attribute value of the 'itemprop'. See below:
<div class="my-attributes">
<div class="row">
<div class="SameClass"><strong>Availability</strong></div>
<div class="SameClass-value" itemprop="avail">In Stock</div>
</div>
<div class="row">
<div class="SameClass"><strong>Quantity</strong></div>
**<div class="SameClass-value" itemprop="qty"> 5 </div>**
</div>
<div class="row">
<div class="SameClass"><strong>Price</strong></div>
<div class="SameClass-value" itemprop="price">250</div>
</div>
How do I get the Quantity into a JavaScript function and return the value of 5? Without having to edit the code of the site itself?
I have been playing with this but I am sure this is completely and utterly incorrect.
function () {
var x = document.getElementsByClassName("SameClass").getAttribute("itemprop");
if (x = 'price')
{
var a = document.getElementsByClassName("SameClass").getAttribute("itemprop").innerText;
return a;
}
}
The following might work for you:
function getQty() {
var arr=document.getElementsByClassName("SameClass-value");
for(var i=0;i<arr.length;i++)
if (arr[i].getAttribute("itemprop") == 'qty') return arr[i].innerHTML;
}
Or, even shorter, you can do
function getQty() {
return document.getElementsByClassName("SameClass-value")
.find(d=>d.getAttribute("itemprop") == 'qty').innerHTML;
}
Sorry for the repeated edits. It's been a long day for me today and I was trying to quickly put something together on my little smartphone.
If the classes don't change, you can select all the relevant elements then get the value from the one you need.
function getQty() {
var qty;
document.querySelectorAll("div.SameClass-value").forEach(function(element) {
if (element.getAttribute("itemprop") === "qty") {
qty = element.innerText;
}
});
return qty;
}
console.log(getQty());
<div class="my-attributes">
<div class="row">
<div class="SameClass"><strong>Condition</strong></div>
<div class="SameClass-value" itemprop="condition">New</div>
</div>
<div class="row">
<div class="SameClass"><strong>Color</strong></div>
<div class="SameClass-value" itemprop="color">Black</div>
</div>
<div class="row">
<div class="SameClass"><strong>Availability</strong></div>
<div class="SameClass-value" itemprop="avail">In Stock</div>
</div>
<div class="row">
<div class="SameClass"><strong>Quantity</strong></div>
<div class="SameClass-value" itemprop="qty"> 5 </div>
</div>
<div class="row">
<div class="SameClass"><strong>Price</strong></div>
<div class="SameClass-value" itemprop="price">250</div>
</div>
</div>
So I have this code
var $divs = $("div.product");
$('#priceAscending').on('click', function() {
var ascendingOrderedDivs = $divs.sort(function(a, b) {
return $(a).find("div.price").text() > $(b).find("div.price").text();
});
$("#container").html(ascendingOrderedDivs);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wrap">
<button id="priceAscending">Price ascending</button>
<!--<button id="priceDescending">Price descending</button>-->
<div id="container">
<div class="product">
<span id="name">Product One</span>
<div class="price">14.85$</div>
</div>
<div class="product">
<span id="name">Product Two</span>
<div class="price">27.59$</div>
</div>
<div class="product">
<span id="name">Product Three</span>
<div class="price">2.64$</div>
</div>
</div>
</div>
I want to sort div.product in ascending order based on the price, but it doesn't work. It puts 2.64 in the middle but it should put it first.
How can I fix this issue using jQuery?
You need to change > to -
return $(a).find("div.price").text() - $(b).find("div.price").text();
You also need to remove $ from price to compare the values. You can do it with str.slice(0, -1)
return $(a).find("div.price").text().slice(0, -1) - $(b).find("div.price").text().slice(0, -1);
Here is a working JSFiddle
I suggest using the numeric value instead of the string
var divs = $("div.product");
$('#priceAscending').on('click', function() {
var ascendingOrderedDivs = divs.sort(function(a, b) {
var aVal = parseFloat($(a).find("div.price").text().replace("$",""));
var bVal = parseFloat($(b).find("div.price").text().replace("$",""));
return aVal - bVal;
});
$("#container").html(ascendingOrderedDivs);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wrap">
<button id="priceAscending">Price ascending</button>
<!--<button id="priceDescending">Price descending</button>-->
<div id="container">
<div class="product">
<span id="name">Product One</span>
<div class="price">14.85$</div>
</div>
<div class="product">
<span id="name">Product Two</span>
<div class="price">27.59$</div>
</div>
<div class="product">
<span id="name">Product Three</span>
<div class="price">2.64$</div>
</div>
</div>
</div>
You could replace the $ at the end of the prices with an empty string and use parseFloat to compare the values. Note that id's on the page should be unique. For all the spans you use id="name
var $divs = $("div.product");
$('#priceAscending').on('click', function() {
var ascendingOrderedDivs = $divs.sort(function(a, b) {
return parseFloat($(a).find("div.price").text().replace(/\$$/, '')) - parseFloat($(b).find("div.price").text().replace(/\$$/, ''));
});
$("#container").html(ascendingOrderedDivs);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wrap">
<button id="priceAscending">Price ascending</button>
<!--<button id="priceDescending">Price descending</button>-->
<div id="container">
<div class="product">
<span id="name">Product One</span>
<div class="price">14.85$</div>
</div>
<div class="product">
<span id="name">Product Two</span>
<div class="price">27.59$</div>
</div>
<div class="product">
<span id="name">Product Three</span>
<div class="price">2.64$</div>
</div>
</div>
</div>
I have a set of DIVs that are displayed like a table, but aren't in an HTML table.
The structure is like this:
<div id="queryResult" style="display: block;">
<div class="rRow">
<div class="rCell4">Job</div>
<div class="rCell4">Company</div>
<div class="rCell4">Customer</div>
<div class="rCell4">Product</div>
<div class="rCell4">Balance</div>
</div>
<div class="rRow">
<div class="rCell4 editMe">46549</div>
<div class="hideMe coID">1</div>
<div class="rCell4 coName">Dry Transload</div>
<div class="rCell4">XYZ co</div>
<div class="rCell4">39.100</div>
<div class="rCell4">26.48550</div>
</div>
<div class="rRow">
<div class="rCell4 editMe">46549</div>
<div class="hideMe coID">1</div>
<div class="rCell4 coName">Dry Transload</div>
<div class="rCell4">MNOP co</div>
<div class="rCell4">39.100</div>
<div class="rCell4">26.48550</div>
</div>
<div class="clr"></div>
</div>
When displayed it looks something like this:
So what I want is to be able to sort the columns by clicking on the column header or something. I know there are jQuery/JavaScript libraries out there like sorttable but all the ones I find are expecting a HTML table.
Do I bite the bullet and just switch this over to a table, or is there another reasonable (easier) solution?
Here is a solution. I added some class to your html for more control.
HTML:
<div id="queryResult" style="display: block;">
<div class="rRow header">
<div class="rCell4">Job</div>
<div class="rCell4">Company</div>
<div class="rCell4">Customer</div>
<div class="rCell4">Product</div>
<div class="rCell4">Balance</div>
</div>
<div class="rRow body">
<div class="rCell4 editMe">46549</div>
<div class="hideMe coID">1</div>
<div class="rCell4 coName">VDry Transload</div>
<div class="rCell4">XYZ co</div>
<div class="rCell4">38.100</div>
<div class="rCell4">18.48550</div>
</div>
<div class="rRow body">
<div class="rCell4 editMe">46623</div>
<div class="hideMe coID">1</div>
<div class="rCell4 coName">Dry Transload</div>
<div class="rCell4">MNOP co</div>
<div class="rCell4">31.100</div>
<div class="rCell4">29.48550</div>
</div>
<div class="rRow body">
<div class="rCell4 editMe">46145</div>
<div class="hideMe coID">1</div>
<div class="rCell4 coName">ADry Transload</div>
<div class="rCell4">JKH co</div>
<div class="rCell4">42.100</div>
<div class="rCell4">16.48550</div>
</div>
<div class="clr"></div>
</div>
And here is a jQuery to do sorting:
jQuery:
$('.header').children('.rCell4').each(function(index){
$(this).click(function(){
var container = $('#queryResult');
var header = $('.header');
var cmpCols = [];
$('.body').each(function(){
cmpCols.push($(this).children('.rCell4').eq(index));
});
for(i=0; i<cmpCols.length-1; i++){
for(j=i; j<cmpCols.length; j++){
if(cmpCols[i].text() > cmpCols[j].text()){
var tmp = cmpCols[i];
cmpCols[i] = cmpCols[j];
cmpCols[j] = tmp;
}
}
}
container.html(header);
for(i=0; i<cmpCols.length; i++){
container.append(cmpCols[i].parent());
}
});
});
Working jsFiddle Example.
If you gave each of your <div class="rRow"> elements a unique id, you could reorder them using jQuery .insertAfter();
e.g. for
<div class="rRow" id="row1">
...
</div>
<div class="rRow" id="row2">
...
</div>
you use $('#row1').insertAfter('#row2'); to flip the position of the two rows.
Then you just need a function which will read each value in a particular "column" in response to an onclick event on the header, get the values in that column, sort them, and reorder the rows.
here is my HTML code
<div id="parent">
<div id="computer">
<div id="items">
<div id="1">hp</div>
<div id="2">compaq</div>
<div id="3">toshiba</div>
</div>
</div>
<div id="laptop">
<div id="1">i5</div>
<div id="2">dual core</div>
<div id="3">i3</div>
</div>
<div id="printer">
<div id="laser">hp laser</div>
</div>
<div id="cpu">
<div id="item">
<div id="1">pintuim</div>
<div id="2">celeron</div>
</div>
</div>
<div id="scanner">
<div id="canon">
<div>canon</div>
</div>
</div>
</div>`
I am trying to get the id of each first element of the parent div
that is to get an
array=[computer, laptop, printer, cpu, scanner]
here is my jquery code but it's taking everything.
var a = $("div.content :nth-child(1)")find("*").toArray();
please I need some help thanks
there is a selector in jQuery which will return the first level of children: DEMO
var a=[];
$("#parent > div").each(function(){ // using > will return the first level of children
a.push($(this).attr('id'));
});
alert(a);
Those are children of the #parent element so you can iterate over that and create an array out of it using .map()
var array = $('#parent').children().map(function() {
return this.id;
}).get();
snippet.log(array)
<!-- Provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="parent">
<div id="computer">
<div id="items">
<div id="1">hp</div>
<div id="2">compaq</div>
<div id="3">toshiba</div>
</div>
</div>
<div id="laptop">
<div id="1">i5</div>
<div id="2">dual core</div>
<div id="3">i3</div>
</div>
<div id="printer">
<div id="laser">hp laser</div>
</div>
<div id="cpu">
<div id="item">
<div id="1">pintuim</div>
<div id="2">celeron</div>
</div>
</div>
<div id="scanner">
<div id="canon">
<div>canon</div>
</div>
</div>
</div>
I'm not sure if this is possible. I can't seem to even get started but I have the following HTML. Is it possible to click on a title (Column 1, Column 2 or Column 3) and have everything in the bodyModule get sorted?
<div class="moduleRowTitle">
<div class="column1">Column 1</div>
<div class="column2">Column 2</div>
<div class="column3">Column 3</div>
</div>
<div class="bodyModule">
<div class="row">
<div class="column1">AAAAA</div>
<div class="column2">BBBBB</div>
<div class="column3">CCCCC</div>
</div>
<div class="row">
<div class="column1">BBBBB</div>
<div class="column2">AAAAA</div>
<div class="column3">CCCCC</div>
</div>
<div class="row">
<div class="column1">BBBBB</div>
<div class="column2">CCCCC</div>
<div class="column3">AAAAA</div>
</div>
</div>
Clicking on column2 should sort as the following:
<div class="row">
<div class="column1">BBBBB</div>
<div class="column2">AAAAA</div>
<div class="column3">CCCCC</div>
</div>
<div class="row">
<div class="column1">AAAAA</div>
<div class="column2">BBBBB</div>
<div class="column3">CCCCC</div>
</div>
<div class="row">
<div class="column1">BBBBB</div>
<div class="column2">CCCCC</div>
<div class="column3">AAAAA</div>
</div>
Demo FIDDLE
Jquery
$(document).ready(function(){
$('.moduleRowTitle div').click(function(){
var vals = [];
var className=$(this).attr('class');
$( ".bodyModule ."+className).each(function(){
vals.push($(this).html());
});
vals.sort();
var i=0;
$( ".bodyModule ."+className).each(function(){
$(this).html(vals[i]);
i=i+1;
});
});
});
I hope this is what you expect