Problem using .sort to sort elements alphabetically - javascript

Am having a problem with sorting using jquery.The elements not getting sorted.I used javascript .sort but this works fine with me if the attribute is numbers but not text.
I can solve the issue using append but this is not what am willing to use.
Can some one please trouble shoot this code.
jQuery(document).ready(function($) {
var divList = $(".listing-item");
var gg = divList.get().sort(function(a, b) {
return $(a).data("listing-title") < $(b).data("listing-title");
});
console.log(gg);
$("#list").html(divList);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="list">
<div class="listing-item" data-listing-title="a">
a
</div>
<div class="listing-item" data-listing-title="z">
z
</div>
<div class="listing-item" data-listing-title="b">
b
</div>
<div class="listing-item" data-listing-title="c">
c
</div>
</div>

Try using .localeCompare(). I have pull this working content from jQuery - Sorting div contents
<!DOCTYPE html>
<htm>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.0/jquery.min.js"></script>
<script>
$(document).ready(function(){
var divList = $(".listing-item");
divList.sort(function(a, b) {
return $(a).data("listing-title").toUpperCase().localeCompare($(b).data("listing-title").toUpperCase());
});
$("#list").html(divList);
});
</script>
</head>
<body>
<div id="list">
<div class="listing-item" data-listing-title="a">a</div>
<div class="listing-item" data-listing-title="z">z</div>
<div class="listing-item" data-listing-title="b">b</div>
<div class="listing-item" data-listing-title="c">c</div>
</div>
</body>
</html>
See also similar question How may I sort a list alphabetically using jQuery?

you just need to return a number in the sorting function. Return -1 if the first should be placed before the second. So sort ascending
You can add more conditions.
if($(a).data("listing-title") > $(b).data("listing-title")) return 1 -> descending
if($(a).data("listing-title") = $(b).data("listing-title")) return 0 -> no sorting
and put in the HTML the sorted list ( gg instead of divList)
jQuery(document).ready(function($) {
var divList = $(".listing-item");
var gg = divList.get().sort(function(a, b) {
if($(a).data("listing-title") < $(b).data("listing-title")) {
return -1 ;
}
});
console.log(gg);
$("#list").html(gg);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="list">
<div class="listing-item" data-listing-title="a">
a
</div>
<div class="listing-item" data-listing-title="z">
z
</div>
<div class="listing-item" data-listing-title="b">
b
</div>
<div class="listing-item" data-listing-title="c">
c
</div>
</div>

you don't need jQuery for this, and I think the problem is your comparison function, something like this, should make the job for you:
//First select the items
const items = document.querySelectorAll('div#list > .listing-item');
//Next, transform this to an array using `from`, then compare
//using `sort`, finally iterate over the sorted array using `forEach`,
//and append element in the sorted array to the `#list`.
//
Array
.from(items)
.sort((x,y) => {
const valueX = x.dataset.listingTitle;
const valueY = y.dataset.listingTitle;
if(valueX > valueY) return 1;
else if(valueX < valueY) return -1;
else return 0;
})
.forEach(element => document.getElementById('list').appendChild(element));

Related

shorter way to check if a title exists

Checking if a title already exists. Is there a shorter way? Something like:
if(test.exists.inside('.title'){...
var x = 0;
var test = $('#test').text();
$('.title').each(function(){
if($(this).text() == test){x = 1;}
});
if(x == 1){console.log('exists');}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class='title'>lorem</div>
<div class='title'>ipsum</div>
<div class='title'>lorema</div>
<div class='title'>ipsuma</div>
<div id='test'>lorem</div>
a lot of ways to do this :contains , filter() with indexOf() and filter() with text equal test.. depending on what you're trying to do
var x = 0;
var test = $('#test').text();
var Exists = $('.title:contains("'+test+'")').length;
console.log('Yes '+Exists+ ' title with text '+test);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class='title'>lorem</div>
<div class='title'>ipsum</div>
<div class='title'>lorema</div>
<div class='title'>ipsuma</div>
<div id='test'>lorem</div>
you can check also with for contains text check
$('.title:contains("'+test+'")').length > 0
OR for exact text check
$('.title').filter(function(){
return $(this).text().trim() == test;
}).length > 0
Note: :contains and .indexOf search for the text contains text not the exact text .. by using $(this).text().trim() == test; this
will return the exact text element
If you're just looking for shorter code, one option would be to invoke Array.prototype.some, and rather than store the result of .text() in a variable, invoke it every time, to save on characters typed:
if ([].some.call($('.title'), d => $(d).text() === $('#test').text())) {
console.log('exists');
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class='title'>lorem</div>
<div class='title'>ipsum</div>
<div class='title'>lorema</div>
<div class='title'>ipsuma</div>
<div id='test'>lorem</div>
Personally, I'd prefer readability over code length:
const textToFind = $('#test').text();
const exists = Array.prototype.some.call(
$('.title'),
title => $(title).text() === textToFind
);
if (exists) {
console.log('exists');
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class='title'>lorem</div>
<div class='title'>ipsum</div>
<div class='title'>lorema</div>
<div class='title'>ipsuma</div>
<div id='test'>lorem</div>

Traverse the DOM and get IDs

With the following HTML:
<div id="main">
<div id="a">
qq
qw
qe
</div>
<div id="b">
qa
qs
qd
</div>
<div id="c">
qz
qx
qc
qv
</div>
</div>
I want to get a list of all the IDs:
a, a!1, a!3, a!2, b, b!1, b!2, b!3, c, c!1, c!2, c!3, c!4
The following code kind of does that:
var arr = $("#main > div").map(function() {
return this.id
});
var aa = (arr.get().join(","));
alert(aa);
but the alert only gives me" "a,b,c"
Is there a better way to do this that I may be missing so it will transverse the DOM of a specific container ID and pass back all the child IDs of all the elements in the container?
Use css selectors in JQuery to iterate through all, instead of direct children:
$(function(){
$('#main *').each(function (){
var id = $(this).attr('id');
console.log(id);
$('#main').append("<br /> -"+id);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="main">
<div id="a">
qq
qw
qe
</div>
<div id="b">
qa
qs
qd
</div>
<div id="c">
qz
qx
qc
qv
</div>
</div>
Just do
var arr = $("#main > div, #main > div > a").map(function() {
return this.id
});
Your current code gives the id of direct children of #main but not of a
Just add anchors to query:
$("#main div, #main a")
Codepen
var ids = []
$("a").each(function(){
ids.push($(this).attr("id"))
})
var total_id='';
$('#main *').each(function(){
total_id+=$(this).attr('id')+',';
})
console.log(total_id);
Please try this.

Extracting value from a div sent in to javascript

Im attempting to get the ID of the specific box that i call.
<div id="box1" onmouseover="transition(box1)" onmouseout="detransition(box1)">
<div class="box1-smallbox">
</div>
function transition(prop){
document.getElementsByTagName(prop + "-smallbox").style.marginLeft = X;
}
I want to get that prop = box1. For a easy system that then can be used with 10 or 20 boxes.
Thanks in advance!
without jquery, only javascript:
<div id="box1" onmouseover="transition(this.id)" onmouseout="detransition(this.id)">
<div class="box1-smallbox">aaa</div>
</div>
<div id="box2" onmouseover="transition(this.id)" onmouseout="detransition(this.id)">
<div class="box2-smallbox">bbb</div>
</div>
<div id="box3" onmouseover="transition(this.id)" onmouseout="detransition(this.id)">
<div class="box3-smallbox">ccc</div>
</div>
<script type="text/javascript" language="javascript">
function transition(prop){
var els = document.getElementsByTagName("div");
for(var i=0;i<els.length;i++){
if(els[i].className==prop+"-smallbox"){
els[i].style.marginLeft = 200;
}
}
}
function detransition(prop){
var els = document.getElementsByTagName("div");
for(var i=0;i<els.length;i++){
if(els[i].className==prop+"-smallbox"){
els[i].style.marginLeft = 0;
}
}
}
</script>
Turn it into a string since you want to pass it's id as string
onmouseover="transition('box1')"

tSort on jQuery object

I'm trying to sort the results of a jQuery selection with tSort.
HTML:
<div sort="2"></div>
<div sort="3"></div>
<div sort="1"></div>
<div sort="4"></div>
<div sort="6"></div>
<div sort="5"></div>
Javascript:
<script>
$sort_order = $('div').tsort({attr:'sort'});
</script>
I want the result to be: 1,2,3,4,5,6 in the jQuery object, not yet inserted into the page.
Is this possible with tSort, or should I write my own algorithm?
It is easier to do it if there is a wrapper of all the div elements.
HTML:
<div id="wrapper">
<div sort="2">2</div>
<div sort="3">3</div>
<div sort="1">1</div>
<div sort="4">4</div>
<div sort="6">6</div>
<div sort="5">5</div>
</div>
Javascript (with jQuery):
var $wrapper = $('#wrapper');
$wrapper.find('div').sort(function (a, b) {
return +a.getAttribute('sort') - +b.getAttribute('sort');
})
.appendTo($wrapper);
Working demo.
In response to #Tim's comment, you can place the elements that do not have the sort attributes at the back of the wrapper element easily, even without jQuery.
Assuming that this is your HTML:
<div id="wrapper">
<div style="color:red;">red color, without sort attribute</div>
<div style="color:red;" sort="7">red color (sort attribute=7)</div>
<div sort="2">2</div>
<div sort="3">3</div>
<div sort="1">1</div>
<div sort="4">4</div>
<div sort="6">6</div>
<div sort="5">5</div>
</div>
You can place the element(s) that do not have the sort attribute by having this as your Javascript:
// As shown earlier above,
var $wrapper = $('#wrapper');
$wrapper.find('div').sort(function (a, b) {
return +a.getAttribute('sort') - +b.getAttribute('sort');
})
.appendTo($wrapper);
// New code to add:
var divs = document.getElementsByTagName('div');
for(var i = 0; i < divs.length; i++) {
if(divs[i].getAttribute('sort') == null || divs[i].getAttribute('sort') == undefined) {
divs[i].parentNode.appendChild(divs[i]);
}
}
Working demo.
clone it before using .tsort
$sort_order = $('div').clone().tsort({attr:'sort'});
DEMO

JQuery get a contiguous sequence of elements

I'm trying to get a contiguous array of elements using JQuery. For example for the this html:
<div class="parent">
<div class="childType2">1</div>
<div class="childType2">2</div>
<div class="childType2">3</div>
<div class="childType1">4</div>
<div class="childType1">5</div>
<div class="childType1">6</div>
<div class="childType1">7</div>
<div class="childType2">8</div>
<div class="childType1">9</div>
<div class="childType1">10</div>
<div class="childType1">11</div>
<div class="childType1">12</div>
</div>
I want it to return the div's containing 4,5,6,7 (The first sequnce of the divs with the class="childType1").
I tried to do
$("<div>test</div>")($('.parent .childType2').siblings('.childType1').addBack());
But this of course will add the div with the text test after the last childType1 (12).
I'm not so good with JQuery.
Edit:
Since the div's are dynamically generated, I ended up adding for each "group" a special class post-fix of the id related to his group, and used the method described in suspectus's answer. Not exactly what i had in mind, but it works :D.
You can use either .each (docs) or .filter (docs). If you use .filter() you can chain another jQuery method after it.
var state = 0;
var elements = [];
$('.parent div').each( function( i, elem ) {
if( state != 2 && elem.className === "childType1" ) {
state = 1;
elements.push( elem );
} else if ( state == 1 ) {
state = 2;
}
} );
console.log( elements );
Or more jQuery approach:
var state = 0;
$('.parent div').filter( function() {
if( state != 2 && $(this).hasClass( "childType1" ) ) {
state = 1;
return true;
} else if ( state == 1 ) {
state = 2;
}
return false;
} ).css( 'background-color', 'red' );
<div class="parent">
<div class="childType2">1</div>
<div class="childType2">2</div>
<div class="childType2">3</div>
<div class="childType1 inner">4</div>
<div class="childType1 inner">5</div>
<div class="childType1 inner">6</div>
<div class="childType1 inner">7</div>
<div class="childType2">8</div>
<div class="childType1">9</div>
<div class="childType1">10</div>
<div class="childType1">11</div>
<div class="childType1">12</div>
</div>
$(".inner") // gives the elements required
You could use filter for this :
var $elements = $(".childType1").filter(function() {
var no = parseInt($(this).text(), 10)
return (( no > 3) && ( no < 8))
});
now $elements will contain only those matched elements between 3 and 8 ie., 4 to 7.
You can use .each() method for looping all the divs having class="childType1"
Following is the complete code. Modify it according to your need.
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js"></script>
<script type="text/javascript">
$(function () {
$(".childType1").each(function (i) {
if ( $(this).html() == "4" ||$(this).html() == "5" || $(this).html() == "6" ||$(this).html() == "7") {
alert($(this).html());
}
});
});
</script>
</head>
<body>
<div class="parent">
<div class="childType2">1</div>
<div class="childType2">2</div>
<div class="childType2">3</div>
<div class="childType1">4</div>
<div class="childType1">5</div>
<div class="childType1">6</div>
<div class="childType1">7</div>
<div class="childType2">8</div>
<div class="childType1">9</div>
<div class="childType1">10</div>
<div class="childType1">11</div>
<div class="childType1">12</div>
</div>
</body>
</html>

Categories

Resources