I have the following HTML structure:
<div class="col col1">
<div class="colSub1"></div>
<div class="colSub1"></div>
</div>
<div class="col col2">
<div class="colSub2"></div>
<div class="colSub2"></div>
<div class="colSub2"></div>
</div>
<div class="col col3">
<div class="colSub3"></div>
<div class="colSub3"></div>
</div>
I want to sort this like this, without the parent div:
<div class="colSub1"></div>
<div class="colSub2"></div>
<div class="colSub3"></div>
<div class="colSub1"></div>
<div class="colSub2"></div>
<div class="colSub3"></div>
<div class="colSub2"></div>
What is the most effective and fastest way to do this?
The steps:
Find the element with the largest number of "children".
Loop over the max number and in the columns so in each iteration it will take from the .col one item.
If something not clear, please let me know.
The working code:
var cols = $('.col');
var max = Math.max.apply(null, cols.map(function() {
return $(this).children().length;
}).get());
for (var i = 0; i < max; i++) {
for (var j = 0; j < cols.length; j++) {
$('#result').append(cols.eq(j).children().eq(i).clone());
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h3>Before</h3>
<div class="col col1">
<div class="colSub1">col1 - colSub1</div>
<div class="colSub1">col1 - colSub1</div>
</div>
<div class="col col2">
<div class="colSub2">col2 - colSub2</div>
<div class="colSub2">col2 - colSub2</div>
<div class="colSub2">col2 - colSub2</div>
</div>
<div class="col col3">
<div class="colSub3">col3 - colSub3</div>
<div class="colSub3">col3 - colSub3</div>
</div>
<hr />
<h3>After</h3>
<div id="result"></div>
http://jsbin.com/lavemu/edit?html,js
Related
I would like to archive the below by using JavaScript (or with jQuery). Here is the HTML structure:
<div class="score-set">
<div class="score-item">A<div id="score">96+</div></div>
<div class="score-item">B<div id="score">99</div></div>
<div class="score-item">C<div id="score">99</div></div>
<div class="score-item">D<div id="score">96-</div></div>
</div>
<div class="score-set">
<div class="score-item">A<div id="score">86</div></div>
<div class="score-item">B<div id="score">88</div></div>
<div class="score-item">C<div id="score">90</div></div>
<div class="score-item">D<div id="score">90+</div></div>
</div>
<div class="score-set">
<div class="score-item">A<div id="score">83-</div></div>
<div class="score-item">B<div id="score">83+</div></div>
<div class="score-item">C<div id="score">76</div></div>
<div class="score-item">D<div id="score">78</div></div>
</div>
The JavaScript will do the modification, and the desired results will be B 99 C90 A 83- , which looks like:
<div class="score-set">
<div class="score-item">B<div id="score">99</div></div>
</div>
<div class="score-set">
<div class="score-item">C<div id="score">90</div></div>
</div>
<div class="score-set">
<div class="score-item">A<div id="score">83-</div></div>
</div>
The rules are:
Ignore all non-number in id="score", eg. + and -, and do the ranking.
Show one highest score item.
If two score items are the same in a set, show just one according to the div item sequence inside <div class="score-set">, ie. in the above example A > B > C > D.
When writing the result, write the original div item, including + or -.
To be able to do this, it would be best to get each individual score-set and treat one after another.
For each score item, we need to first get the score and transform it (Array#map) into a number with no digits (.replace(\/D+/g, ''))and memorize the score item html object.
Number(scoreItem.querySelector('div').innerText.replace(/\D+/g, ''))
We can then sort the remaining ones in descending order and simply take the first one of the list. Can be done with Array#sort and destructuring assignment.
.sort(({ score: scoreA }, { score: scoreB }) => scoreB - scoreA)
Then finally we update the score set html.
scoreSet.innerHTML = '';
scoreSet.appendChild(scoreItem);
const scoreSets = document.getElementsByClassName('score-set');
for(const scoreSet of scoreSets){
const [{ scoreItem }] = Array
.from(scoreSet.getElementsByClassName('score-item'), scoreItem => ({
scoreItem,
// it would be better here to access the score using the id
// but `score` is used multiple times which makes getting
// the score element unreliable
score: Number(scoreItem.querySelector('div').innerText.replace(/\D+/g, ''))
}))
.sort(({ score: scoreA }, { score: scoreB }) => scoreB - scoreA)
scoreSet.innerHTML = '';
scoreSet.appendChild(scoreItem);
}
<div class="score-set">
<div class="score-item">A
<div id="score">96+</div>
</div>
<div class="score-item">B
<div id="score">99</div>
</div>
<div class="score-item">C
<div id="score">99</div>
</div>
<div class="score-item">D
<div id="score">96-</div>
</div>
</div>
<div class="score-set">
<div class="score-item">A
<div id="score">86</div>
</div>
<div class="score-item">B
<div id="score">88</div>
</div>
<div class="score-item">C
<div id="score">90</div>
</div>
<div class="score-item">D
<div id="score">90+</div>
</div>
</div>
<div class="score-set">
<div class="score-item">A
<div id="score">83-</div>
</div>
<div class="score-item">B
<div id="score">83+</div>
</div>
<div class="score-item">C
<div id="score">76</div>
</div>
<div class="score-item">D
<div id="score">78</div>
</div>
</div>
This can be MUCH simplified
Note I changed the invalid ID to class="score"
If you cannot do that, then change .querySelector(".score") to .querySelector("div")
document.querySelectorAll('.score-set').forEach(scoreSet => {
const scores = [...scoreSet.querySelectorAll(".score-item")];
scores.sort((a,b) => parseInt(b.querySelector(".score").textContent) - parseInt(a.querySelector(".score").textContent))
scoreSet.innerHTML ="";
scoreSet.append(scores[0])
})
<div class="score-set">
<div class="score-item">A
<div class="score">96+</div>
</div>
<div class="score-item">B
<div class="score">99</div>
</div>
<div class="score-item">C
<div class="score">99</div>
</div>
<div class="score-item">D
<div class="score">96-</div>
</div>
</div>
<div class="score-set">
<div class="score-item">A
<div class="score">86</div>
</div>
<div class="score-item">B
<div class="score">88</div>
</div>
<div class="score-item">C
<div class="score">90</div>
</div>
<div class="score-item">D
<div class="score">90+</div>
</div>
</div>
<div class="score-set">
<div class="score-item">A
<div class="score">83-</div>
</div>
<div class="score-item">B
<div class="score">83+</div>
</div>
<div class="score-item">C
<div class="score">76</div>
</div>
<div class="score-item">D
<div class="score">78</div>
</div>
</div>
I need to move some text from demoBoxA to demoBoxB.
The demoBoxA parent element has an id selector, but the child element below it has no identifiable selector.
Is it possible to select the text content directly? Then move it into the demoBoxB sub-element (the demoBoxB sub-element has an id selector)
There are 2 difficulties with this issue.
The content of demoBoxA is dynamically generated by the program and the sort is not fixed. There are no identifiable selectors for the subelements.
only need to select part of the content. For example, in the example below, just move the phone model text of "Google", "Huawei", "BlackBerry".
Any help, thanks in advance!
<div class="container" id="demoBoxA">
<div class="row">
<div class="col-md-6">Samsung</div>
<div class="col-md-6">Galaxy S10</div>
</div>
<div class="row">
<div class="col-md-6">Google</div>
<div class="col-md-6">Pixel 4</div>
</div>
<div class="row">
<div class="col-md-6">Sony</div>
<div class="col-md-6">Xperia 5</div>
</div>
<div class="row">
<div class="col-md-6">Huawei</div>
<div class="col-md-6">Mate 30 5G</div>
</div>
<div class="row">
<div class="col-md-6">BlackBerry</div>
<div class="col-md-6">KEY2</div>
</div>
<div class="row">
<div class="col-md-6">Apple</div>
<div class="col-md-6">iPhone 8</div>
</div>
</div>
<div class="container" id="demoBoxB">
<div class="row">
<div class="col-md-6">Google</div>
<div class="col-md-6" id="pixel"></div>
</div>
<div class="row">
<div class="col-md-6">Huawei</div>
<div class="col-md-6" id="mate"></div>
</div>
<div class="row">
<div class="col-md-6">BlackBerry</div>
<div class="col-md-6" id="key2"></div>
</div>
</div>
You can chain selectors like this:
var rows = document.querySelectorAll("#demoBoxA > .row");
That will return a list of all rows inside of demoBoxA. If you need more info about chaining selectors, you can read about it here.
Then, to move the rows you can do this:
var demoBoxB = document.getElementById('demoBoxB');
rows.forEach((row) => {
demoBoxB.appendChild(row);
});
If you just want the text inside each of the columns, you can do this:
var columns = document.querySelectorAll("#demoBoxA > .col-md-6");
var texts = [];
columns.forEach((column) => {
texts.push(column.innerText);
});
Now, texts is an array of the text contents of each column.
If you want to select the cellphone models for each brand, you can do this:
var cols = Array.from(document.querySelectorAll("#demoBoxA > .col-md-6"));
var samsungCol = cols.find((col) => {
return col.textContent == "Samsung";
});
var samsungPhones = [];
samsungCol.parentNode.childNodes.forEach((col) => {
if (col != samsungCol) {
samsungPhones.push(col);
}
});
Now, samsungPhones is a list of columns, one for each Samsung phone (for example).
You can use html drag api .
Just add draggable=true for elements you want to drag and add event listeners for dragstart and dragend
html
<div class="container" id="demoBoxA">
<div class="row " draggable="true">
<div class="col-md-6">Samsung</div>
<div class="col-md-6">Galaxy S10</div>
</div>
<div class="row" draggable="true">
<div class="col-md-6">Google</div>
<div class="col-md-6">Pixel 4</div>
</div>
<div class="row" draggabble="true">
<div class="col-md-6">Sony</div>
<div class="col-md-6">Xperia 5</div>
</div>
</div>
<div class="container " id="demoBoxB">
<div class="row " draggable="true">
<div class="col-md-6">Google</div>
<div class="col-md-6" id="pixel"></div>
</div>
<div class="row" draggable="true">
<div class="col-md-6">Huawei</div>
<div class="col-md-6" id="mate"></div>
</div>
<div class="row" draggable="true">
<div class="col-md-6">BlackBerry</div>
<div class="col-md-6" id="key2"></div>
</div>
</div>
js
document.addEventListener('dragstart', function(e)
{
item = e.target;
}, false);
document.addEventListener('dragend', function(e)
{
document.getElementById("demoBoxB").appendChild(item)
}, false);
Note : you might have to add conditions to check whether the drop is actually happening in demoboxB
Im looking for elegant way to select only divs on left hand side (marked green).
Number of elements is unknown, so i cannot rely on .eq() or any other function used for filtering elements.
Thank you for any advice.
Html:
<div class="row">
<div class="col-sm-6">
<div>
</div>
</div>
<div class="col-sm-6">
<div>
</div>
</div>
<div class="col-sm-6">
<div>
</div>
</div>
<div class="col-sm-6">
<div>
</div>
</div>
<div class="col-sm-6">
<div>
</div>
</div>
<div class="col-sm-6">
<div>
</div>
</div>
For each div... If its left offset is less than the 3rd one...
It has to be selected.
//Find the offset position of the 3rd div
offset3 = $(".col-sm-6").eq(2).offset().left;
$(".col-sm-6").each(function(){
if($(this).offset().left < offset3){
SelectIt = $(this).children("div"); // Select the "green" inner div
// Do something with SelectIt...
}
});
Try this :
//Select the first 2 elements of each row
var rowSize = 4;
$("div.col-sm-6").filter(function() {
return $(this).index() % rowSize < 2;
});
Demo:
$("div.col-sm-6").filter(function() {
return $(this).index() % 4 < 2
}).addClass('selected');
.selected {
background-color:green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="row">
<div class="col-sm-6">
<div>1
</div>
</div>
<div class="col-sm-6">
<div>2
</div>
</div>
<div class="col-sm-6">
<div>3
</div>
</div>
<div class="col-sm-6">
<div>4
</div>
</div>
<div class="col-sm-6">
<div>5
</div>
</div>
<div class="col-sm-6">
<div>6
</div>
</div>
<div class="col-sm-6">
<div>7
</div>
</div>
<div class="col-sm-6">
<div>8
</div>
</div>
You may use first-child & nth-child.
Hope this snippet will be useful
$("#demoTable tr td:first-child").addClass("myClass");
$("#demoTable tr td:nth-child(2)").addClass("myClass");
JSFIDDLE
Note: I tried with table you can check with div.row
I have the following HTML structure (endless) ...
<div class="wrapper">
<div class="content">
<div class="score">1</div>
<div class="score">2.5</div>
<div class="score">1.5</div>
<div class="score">1.5</div>
<div class="score">2</div>
</div>
</div>
... and I want, that the script adding score 1 till 5 for every wrapper. The result of every wrapper should displayed in a new div, called "result". This div should be created by the script too.
It would look like this::
<div class="wrapper">
<div class="content">
<div class="score">1</div>
<div class="score">2.5</div>
<div class="score">1.5</div>
<div class="score">1.5</div>
<div class="score">2</div>
<div class="result">8.5</div> <-- created by script
</div>
</div>
<div class="wrapper">
<div class="content">
<div class="score">2.5</div>
<div class="score">3.5</div>
<div class="score">4</div>
<div class="score">1.5</div>
<div class="score">1</div>
<div class="result">12.5</div> <-- created by script
</div>
</div>
<div class="wrapper">
<div class="content">
<div class="score">4</div>
<div class="score">1.5</div>
<div class="score">2.5</div>
<div class="score">2</div>
<div class="score">1.5</div>
<div class="result">11.5</div> <-- created by script
</div>
</div>
My problems:
a) How can I adding the scores for every wrapper correct, if the class name would be always the same (wrapper, content, score)?
b) How can I create a div with the result for every wrapper automatically?
Can anyone help me?
Iterate over each .content element and then append the sum of the .score elements.
You can achieve this by nesting .each() loops:
Example Here
$('.wrapper .content').each(function () {
var sum = 0;
$(this).find('.score').each(function () {
sum += Number($(this).text(), 10);
});
$(this).append('<div class="result">' + sum + '</div>');
});
$('.wrapper .content').each(function () {
var sum = 0;
$(this).find('.score').each(function () {
sum += Number($(this).text(), 10);
});
$(this).append('<div class="result">' + sum + '</div>');
});
.result {
color: #f00;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
<div class="content">
<div class="score">1</div>
<div class="score">2.5</div>
<div class="score">1.5</div>
<div class="score">1.5</div>
<div class="score">2</div>
</div>
</div>
<div class="wrapper">
<div class="content">
<div class="score">2.5</div>
<div class="score">3.5</div>
<div class="score">4</div>
<div class="score">1.5</div>
<div class="score">1</div>
</div>
</div>
<div class="wrapper">
<div class="content">
<div class="score">4</div>
<div class="score">1.5</div>
<div class="score">2.5</div>
<div class="score">2</div>
<div class="score">1.5</div>
</div>
</div>
Without jQuery:
Example Here
var content = document.querySelectorAll('.wrapper .content');
Array.prototype.forEach.call(content, function (el) {
var score = el.querySelectorAll('.score'),
resultElement = document.createElement('div'),
sum = 0;
Array.prototype.forEach.call(score, function (el) {
sum += Number(el.textContent, 10);
});
resultElement.className += 'result';
resultElement.textContent = sum;
el.appendChild(resultElement);
});
$(document).ready(function(){
$('.content').each(function(){
var total = 0;
$(this).find('> .score').each(function(){
total += parseFloat($(this).text());
});
$(this).append('<div class="result">' + total + '</div>');
});
});
Working Demo
You can use jQuery's DOM each:
var finalVal = 0;
$(function () {
$(".content").each(function () {
finalVal = 0;
$(this).find(".score").each(function () {
finalVal += Number($(this).text());
});
$(this).append('<div class="result">' + finalVal + '</div>');
finalVal = 0;
});
});
.result {background: #99f;}
<script src="https://code.jquery.com/jquery-1.9.1.js"></script>
<div class="wrapper">
<div class="content">
<div class="score">1</div>
<div class="score">2.5</div>
<div class="score">1.5</div>
<div class="score">1.5</div>
<div class="score">2</div>
</div>
</div>
<div class="wrapper">
<div class="content">
<div class="score">2.5</div>
<div class="score">3.5</div>
<div class="score">4</div>
<div class="score">1.5</div>
<div class="score">1</div>
</div>
</div>
<div class="wrapper">
<div class="content">
<div class="score">4</div>
<div class="score">1.5</div>
<div class="score">2.5</div>
<div class="score">2</div>
<div class="score">1.5</div>
</div>
</div>
Here, I have two different container. First one is group of anchor links. There is no elements in html. Section one different group of content blocks. How to an append elements based on group of content blocks.
Here is my html,
<div id="group1">
<div class="parent1">
</div>
<div class="parent2">
</div>
<div class="parent3">
</div>
</div>
<div id="group2">
<div class="parentMain1">
<div class="content">test</div>
<div class="content">test</div>
<div class="content">test</div>
</div>
<div class="parentMain2">
<div class="content">test</div>
<div class="content">test</div>
</div>
<div class="parentMain3">
<div class="content">test</div>
</div>
</div>
My result should be,
<div id="group1">
<div class="parent1">
1
2
3
</div>
<div class="parent2">
1
2
</div>
<div class="parent3">
1
</div>
</div>
<div id="group2">
<div class="parentMain1">
<div class="content">test</div>
<div class="content">test</div>
<div class="content">test</div>
</div>
<div class="parentMain2">
<div class="content">test</div>
<div class="content">test</div>
</div>
<div class="parentMain3">
<div class="content">test</div>
</div>
</div>
How to achieve this one with jquery?
You can try this code :
// get all direct child of group 2 element
$('#group2').children().each(function (i, e) {
// get direct child of group 2 element's child
var length = $(this).children().length;
// loop over particular length
for (var m = 1; m <= length; m++) {
// create anchor element
$('<a/>', {
href: '#',
text: m
}).appendTo($('div#group1').find('div:eq(' + i + ')')); // append to group 1 element respectively
}
});
DEMO