Sort elements based on specific classname - javascript

I'm trying to order the div based on the col-md-x. First col-md-4 and then col-md-8. I tried the sort function of jQuery in this variant:
var divElement = $('.container').find('.row').sort(sortMe);
function sortMe(a, b) {
return a.className > b.className;
}
$('.container').append(divElement);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="row different col-md-8 left">col-md-8</div>
<div class="row different col-md-4 right">col-md-4</div>
<div class="row different col-md-4 right">col-md-4</div>
<div class="row different col-md-4 left">col-md-4</div>
<div class="row different col-md-8 left">col-md-8</div>
However this is not sorting on my .col-md-x class but is he sorting on all classes (I think). How could I sort specific on the class col-md-x? I tried also .pop() and .split(), but this is not working in combination with the jQuery .sort() function.

var divElement = $('.container').find('.row').sort(sortMe);
function sortMe(a, b) {
return a.className.match(/col-md-(\d)/)[1] - b.className.match(/col-md-(\d)/)[1];
}
$('.container').append(divElement);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<dic class="container">
<div class="row different col-md-8 left">1</div>
<div class="row different col-md-4 right">2</div>
<div class="row different col-md-4 right">3</div>
<div class="row different col-md-4 left">4</div>
<div class="row different col-md-8 left">5</div>
</div>

You may want to write a function that will return the needed class name by it beginning col-md-
$(function() {
var divElement = $('.container').find('.row').sort(sortMe);
function sortMe(a, b) {
return getColMdClassName(a) > getColMdClassName(b);
}
$('.container').append(divElement);
});
function getColMdClassName(obj) {
return $.grep(obj.className.split(" "), function(v, i){
return v.indexOf('col-md-') === 0;
}).join();
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='container'>
<div class="row different col-md-8 left">8</div>
<div class="row different col-md-4 right">4</div>
<div class="row different col-md-4 right">4</div>
<div class="row different col-md-4 left">4</div>
<div class="row different col-md-8 left">8</div>
</div>

You are comparing text in sort function but need to compare integers. see below function
$(function(){
var divElement = $('.container').find('.row').sort(sortMe);
$('.container').append(divElement);
});
function sortMe(a, b) {
var aInt = getInteger(a.className);
var bInt = getInteger(b.className);
return aInt > bInt;
}
function getInteger(classNameList)
{
var int = 0;
var classList = classNameList.split(/\s+/);
for (var i = 0; i < classList.length; i++) {
if (classList[i].indexOf('col-md')!=-1) {
int = parseInt(classList[i].replace('col-md-',''));
}
}
return int;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="row different col-md-8 left">8</div>
<div class="row different col-md-4 right">4</div>
<div class="row different col-md-4 right">4</div>
<div class="row different col-md-4 left">4</div>
<div class="row different col-md-8 left">8</div>
</div>

Pure js variant:
var divs = document.getElementById('divs');
var map = arr => fn => Array.prototype.map.call(arr, fn);
var getN = str => str.substr(str.indexOf('col-md-'), 8).substr(-1);
var res = map(divs.children)(x => x).sort((a, b) => getN(a.className) - getN(b.className));
res.forEach((el, i) => divs.replaceChild(el, divs.childNodes[i]))
<div id="divs">
<div class="row different col-md-8 left">col-md-8</div>
<div class="row different col-md-4 right">col-md-4</div>
<div class="row different col-md-4 right">col-md-4</div>
<div class="row different col-md-4 left">col-md-4</div>
<div class="row different col-md-8 left">col-md-8</div>
</div>

The accepted answer is not working for me on Chrome, please check this old fiddle.
But we can enhance the answer:
HTML (no changes)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<dic class="container">
<div class="row different col-md-8 left">1</div>
<div class="row different col-md-4 right">2</div>
<div class="row different col-md-4 right">3</div>
<div class="row different col-md-4 left">4</div>
<div class="row different col-md-8 left">5</div>
</div>
JavaScript (small changes):
var divElement = $('.container').find('.row').sort(sortMe);
function sortMe(a, b) {
return a.className.match(/col-md-(\d)/)[1] - b.className.match(/col-md-(\d)/)[1];
}
$('.container').append(divElement);
The new fiddle is here.

Related

remove last 5 letters from class in jquery (not vanilla javascript)

<div class="col-md-4 col-sm-6 dsitbl scrl_animxxxxx"></div>
<div class="col-md-4 col-sm-6 dsitbl scrl_dd applexxxxx"></div>
I want to know is there any way in jquery to remove last "xxxxx" from class
Do it like below:-
$(document).ready(function(){
$('div').each(function(){
$(this).attr('class',$(this).attr('class').slice(0,-5));
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="col-md-4 col-sm-6 dsitbl scrl_animxxxxx">Abc</div>
<div class="col-md-4 col-sm-6 dsitbl scrl_dd applexxxxx">Def</div>
Note:-
1. If you want to check first that class have xxxxx in it (at last) or not and then you want to replace,so you can do it like below:-
if (if ($(this).attr('class').substr($(this).attr('class').length - 5) == "xxxxx"){
// remove characters code here
}
Example:-
$(document).ready(function(){
$('div').each(function(){
if ($(this).attr('class').substr($(this).attr('class').length - 5) == "xxxxx"){
$(this).attr('class',$(this).attr('class').slice(0,-5));
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="col-md-4 col-sm-6 dsitbl scrl_animxxxxx">Abc</div>
<div class="col-md-4 col-sm-6 dsitbl scrl_dd applexxxxx">Def</div>
<div class="col-md-4 col-sm-6 dsitbl scrl_dd mango">Ghi</div>
The only way I can think of is by removing the class then adding the changed class back to the element.
$('.applexxxxx').removeClass('applexxxxx').addClass('apple');

Change Image on div onclick()

I want to load different image on different div clicks. How do I know which div is clicked? Do I have to pass the div class as argument?
<script type="javascript">
function ChangeLibaas() {
}
</script>
<div class="Indeximages">
<img src="images/white.png" id="libaasImage" class="img-responsive jubbahImage" alt="" />
</div>
<div class="col-md-12 nopadding customTabs">
<h2>Pick a Colour</h2>
<div class="col-md-3 colourBlue" onclick="ChangeLibaas()"></div>
<div class="col-md-3 colourBlack" onclick="ChangeLibaas()"></div>
<div class="col-md-3 colourGreen" onclick="ChangeLibaas()"></div>
</div>
Simplest inline: pass (this):
<div class="col-md-3 colourBlue" onclick="ChangeLibaas(this)"></div>
and use it :
function ChangeLibaas(theClickedDiv) {
var img = "images/"+
theClickedDiv.className.split("colour")[1].toLowerCase()+".png"; // take the colour
document.getElementById("libaasImage").src=img;
}
To make it all neater, use an attribute and unobtrusive code
window.onload=function() {
var divs = document.querySelectorAll("div.col-md-3");
for (var i=0;i<divs.length;i++) {
divs[i].onclick=function() {
document.getElementById("libaasImage").src="images/"+
this.getAttribute("data-color")+".png";
}
}
}
using
<div class="col-md-3 colourBlue" data-color="blue""></div>
You can pass as an argument, like this:
<div class="col-md-12 nopadding customTabs">
<h2>Pick a Colour</h2>
<div class="col-md-3 colourBlue" onclick="ChangeLibaas(this)"></div>
<div class="col-md-3 colourBlack" onclick="ChangeLibaas(this)"></div>
<div class="col-md-3 colourGreen" onclick="ChangeLibaas(this)"></div>
</div>
And then:
<script type="javascript">
function ChangeLibaas(sender) {
var div = sender;
}
</script>
But it's better if you use event listeners.
I hope it can be useful:
In your html
<div class="Indeximages">
<img src="images/white.png" id="libaasImage" class="img-responsive jubbahImage" alt="" />
</div>
<div class="col-md-12 nopadding customTabs">
<h2>Pick a Colour</h2>
<button class="col-md-3" data-color="colourBlue" onclick="ChangeLibaas(this)">Blue</div>
<button class="col-md-3" data-color="colourBlack" onclick="ChangeLibaas(this)">Black</div>
<button class="col-md-3" data-color="colorGreen" onclick="ChangeLibaas(this)">Green</div>
</div>
In javascript, code looks like:
function ChangeLibaas(origin) {
var color = origin.dataset.color;
var img = document.getElementById('libaasImage');
img.src = color + ".jpg";
}

Loop through an array of div's to determine if every element has a child

I am looping through an array of div's and I need to check to see if every element of the array has a child element.
Running the code below will console.log for each element, however I only want to console.log "a child exists!" on the condition that every tile in tilesArray has a child element. How can this be achieved?
function hasTile(tilesArray){
for(var i = 0; i < tilesArray.length; i++){
console.log(tilesArray[t]);
if(tilesArray[i].firstChild){
console.log("A child exists!");
}else{
console.log("No child.");
}
}
}
index.html
<div class="container" id="tileContainer">
<!-- id listed by row-column notation. -->
<div class="row">
<div class="col-xs-6 col-md-12 tile" id="r1c1" onclick="main(this)"></div>
<div class="col-xs-6 col-md-12 tile" id="r1c2" onclick="main(this)"></div>
<div class="col-xs-6 col-md-12 tile" id="r1c3" onclick="main(this)"></div>
</div>
<div class="row">
<div class="col-xs-6 col-md-12 tile" id="r2c1" onclick="main(this)"></div>
<div class="col-xs-6 col-md-12 tile" id="r2c2" onclick="main(this)"></div>
<div class="col-xs-6 col-md-12 tile" id="r2c3" onclick="main(this)"></div>
</div>
<div class="row">
<div class="col-xs-6 col-md-12 tile" id="r3c1" onclick="main(this)"></div>
<div class="col-xs-6 col-md-12 tile" id="r3c2" onclick="main(this)"></div>
<div class="col-xs-6 col-md-12 tile" id="r3c3" onclick="main(this)"></div>
</div>
</div>
<!-- End of tile container -->
<div class="container" id="turnDisplayContainer">
<div class="row">
<div class="col-xs-9 col-md-6 content" id="userTurnDisplay">
<h4>Your Turn</h4>
</div>
<div class="col-xs-9 col-md-6 content" id="computerTurnDisplay">
<h5>Computer's Turn</h5>
<iframe src="assets/media/loading-wheel.gif" width="50" height="50" scrolling="no" frameBorder="0"></iframe>
</div>
</div>
</div>
<!-- <div class="container" id="timerDisplayContainer">
<div class="row">
<div class="col-xs-18 col-md-12 content" id="timerDisplay">
<h5>Timer</h5>
</div>
</div>
</div> -->
<div class="container btnContainer">
<div class="row">
<button type="button" class="btn btn-danger" id="resetButton">Reset</button>
</div>
</div>
<img class="img img-responsive gameIcon" src="assets/img/green-ring.png" alt="Green Ring Icon" id="userIcon" />
<img class="img img-responsive gameIcon" src="assets/img/red-x.png" alt="Red X Icon" id="computerIcon" />
You should store an additional info in a local variable. Example:
function hasTile(tilesArray){
var bAllHaveChild = tilesArray.length > 0;
for(var i = 0; i < tilesArray.length; i++){
console.log(tilesArray[t]);
if(!tilesArray[i].firstChild){
bAllHaveChild=false;
}
}
if(bAllHaveChild)
console.log("A child exists!");
else
console.log("No child.");
}
I hope it helps. Bye
UPDATED
I came up with a much more performant way of doing this. This particular problem is well suited for XPath via document.evaluate. With XPath you have the ability to create a selection path on elements that have content.
While I believe these should beat out the other options here in a foot race, the XPath typically comes in 5 times faster than the querySelectorAll filtering version.
const xpath = 'boolean(.//div/div/text())'
const hasTileXPath = (id) => document.evaluate(xpath, document.getElementById(id)).booleanValue
const hasTile = (id) => Array.from(
document.querySelectorAll(`#${id} > div > div`)
).filter((x) => x.innerHTML).length > 0
const iterations = 1000
const iterable = Array(iterations).fill().map((x, i) => i)
const pre = performance.now()
for(let i of iterable) {
hasTileXPath('hasNoTiles')
hasTileXPath('hasTiles')
}
const mid = performance.now()
for(let i of iterable) {
hasTile('hasNoTiles')
hasTile('hasTiles')
}
const last = performance.now()
console.info(`XPath: ${iterations} iterations # ${(mid - pre) / 1000}s`)
console.info(`SHOULD NOT HAVE TILES (XPATH) => ${hasTile('hasNoTiles')}`)
console.info(`SHOULD HAVE TILES (XPATH) => ${hasTile('hasTiles')}`)
console.info(`querySelectorAll: ${iterations} iterations # ${(last - mid) / 1000}s`)
console.info(`SHOULD NOT HAVE TILES => ${hasTileXPath('hasNoTiles')}`)
console.info(`SHOULD HAVE TILES => ${hasTileXPath('hasTiles')}`)
<div id="hasNoTiles">
<div>
<div></div>
<div></div>
</div>
<div>
<div></div>
<div></div>
</div>
<div>
<div></div>
<div></div>
</div>
</div>
<div id="hasTiles">
<div>
<div></div>
<div></div>
</div>
<div>
<div></div>
<div>TILE</div>
</div>
<div>
<div></div>
<div>TILE</div>
</div>
</div>
A compact way of doing it would be to check the length of the .tile:empty collection by using querySelectorAll(). If it is 0 then all the divs have child elements; if not then you can loop through the array and console.log them all.
((tiles,len,x)=>{
if(!len=(tiles=document.querySelectorAll(".tile:empty")).length)
console.log("All .tile elements contain child elements.");
else
for(x=0;x<len;x++)
console.log("div#"+tiles[x].id+" does not contain any child elements.");
})();
(Apologies for the lack of a working example or for any potential typos; I wrote this up on my phone - I'll clean it up when I get back to a computer)
You could return out of the function whenever a div without a child is found. That way the console.log won't fire unless all divs has children.
function hasTile(tilesArray){
tilesArray.forEach(function(element) {
if (element.children.length < 1) {
return;
}
});
console.log("a child exists!");
}
var tilesArray = Array.prototype.slice.call(tilesArray);
var fails = tilesArray.some(function(element) {
return element.children.length === 0;
})
if (fails) {
console.log("No child.");
} else {
console.log("A child exists!");
}

Get children under a parent using jQuery

$(document).ready(function() {
$.ajax({
type: "POST",
url: 'some/url',
data: {
'name':'myname'
},
success: function (result) {
var result = ["student", "test"];
var length = result.length;
for (var i = 0; i < length; i++) {
var datastores = result;
$('#data_stores').append(
"<div class='col-sm-8 col-md-8 col-lg-8 col-xs-8 pre-panel datastore' id=" + datastores[i] + "> </div>");
}
}
})
var ids = $('#data_stores').children().map(function(){ return this.id }).get();
$('<pre>').appendTo('body').text(JSON.stringify(ids));
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="data_stores">
</div>
<div id="data_stores">
<div class="col-sm-8 col-md-8 col-lg-8 col-xs-8 pre-panel datastore" id="students">
//Some other codes here
</div>
<div class="col-sm-8 col-md-8 col-lg-8 col-xs-8 pre-panel datastore" id="teachers">
//Some other codes here
</div>
</div>
This is a block of code in my HTML. The inner divs under data_stores are created using jquery. The IDs of the children div were result of an AJAX request and assigned on success.
The problem is, I need the ID values of the children divs to use for another AJAX call.
I ran the following:
console.log($("#data_stores"));
Output I got is the same above.
But for,
console.log($("#data_stores").find('.datastore'));
[prevObject: m.fn.init[1], context: document, selector: "#data_stores
.datstore"]
But, when accessing the child it says the element is undefined.
I need to do both AJAX calls on
$(document).ready(function() {
})
Using children like this works:
var ids = $('#data_stores').children().map(function(){ return this.id }).get();
var ids = $('#data_stores').children().map(function(){ return this.id }).get();
$('<pre>').appendTo('body').text(JSON.stringify(ids));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="data_stores">
<div class="col-sm-8 col-md-8 col-lg-8 col-xs-8 pre-panel datastore" id="students">
//Some other codes here
</div>
<div class="col-sm-8 col-md-8 col-lg-8 col-xs-8 pre-panel datastore" id="teachers">
//Some other codes here
</div>
</div>

Converting HTML element to Int returning NaN Javascript

I am attempting to make a player health counter, however I am still getting NaN returned.. Help
Here is my HTML
<!--player 1 hp-->
<div class="row">
<div class="col-sm-6 col-md-6 col-xs-12 col-lg-6">
<h2 class="text-center" id="play1HP">0</h2>
<button onclick="healthCountUp1()">+1</button>
</div>
And my JavaScript
function healthCountUp1(){
var player1HP = parseInt(document.getElementById("play1HP").value);
var add = player1HP + 1;
document.getElementById("play1HP").innerHTML = player1HP;
}
You need innerHTML and not value. This is happening because the h2 element has not an attribute called value. So when you read the value of the h2 you get undefined and when you pass undefined to the parseInt you get NaN.
var player1HP = parseInt(document.getElementById("play1HP").innerHTML);
h2 element doesn't have value property, so parseInt will return NaN. You need to use innerHTML or textContent to get value. Also you need to update with variable add.
function healthCountUp1() {
var player1HP = parseInt(document.getElementById("play1HP").innerHTML);
var add = player1HP + 1;
document.getElementById("play1HP").innerHTML = add;
}
<div class="col-sm-6 col-md-6 col-xs-12 col-lg-6">
<h2 class="text-center" id="play1HP">0</h2>
<button onclick="healthCountUp1()">+1</button>
</div>
function healthCountUp1() {
var player1HP = parseInt(document.getElementById("play1HP").textContent);
var add = player1HP + 1;
document.getElementById("play1HP").textContent = add;
}
<div class="col-sm-6 col-md-6 col-xs-12 col-lg-6">
<h2 class="text-center" id="play1HP">0</h2>
<button onclick="healthCountUp1()">+1</button>
</div>
you had better make variable to store health value in:
<div class="row">
<div class="col-sm-6 col-md-6 col-xs-12 col-lg-6">
<h2 class="text-center" id="play1HP">0</h2>
<button onclick="healthCountUp1()">+1</button>
</div>
javascript:
var health = 0;
function healthCountUp1(){
health++;
document.getElementById("play1HP").innerHTML = health;
}

Categories

Resources