JQuery dom treeview hierarchy problems - javascript

So, I have this html code.
<div class="test">
A
<div class="test">
B
</div>
</div>
<div class="test">
C
<div class="test">
<div class="test">
D
</div>
E
</div>
</div>
And I am trying to structure the data to something like this using jQuery.
[0] = [0] = <div class="test">A</div>
[1] = <div class="test">B</div>
[1] = [0] = <div class="test">C</div>
[1] = [0] = <div class="test">C</div>
[1] = [1] = <div class="test">E</div>
But the problem I am facing is that I can't make jQuery ignore the first set of DIVS when its finished parsing (A AND B).
This is how far ive come.
getFor($(document).first());
function getFor($prev) {
// look for initial foorloop
var $cur = $prev.find(".class").first();
if (!$cur.length) {
return;
}
// save it
collection.push($cur);
//look for descendants
// has childreN? then create a new array instead?
getFor($cur);
// We found our first hit. go thru nodes
}
console.log(collection);
I know I am on the right path, but without involving .remove() and start from the $(document), I dont know how to get to the second block of .class...
Thanks in advance
/xgx

Related

sort div's through sort(); [duplicate]

This question already has answers here:
Easiest way to sort DOM nodes?
(9 answers)
Closed last month.
I have list and this list must be sort to a => b throught like btn (example click SORT and we have list to a -> b)
<div class = "list">
<div id = "products"> Sugar </div>
<div id = "products"> Banana </div>
<div id = "products"> Apple </div>
</div>
sorted to for button =>
<div class = "list">
<div id = "products"> Apple </div>
<div id = "products"> Banana </div>
<div id = "products"> Sugar </div>
</div>
Idk how did that with like btn :(
I tried something like that =>
// For the HTML //
<button class = 'sortBtn' onclick = 'sort()'>Sort</button>
<script>
const sort = document.quertSelector('.sortBtn');
sort.addEventListenet('click', function sort(a, b){
$parent.sort();
})
</script>
I would be grateful for help :) <3
There's a few issues in your code.
Typo: quertSelector -> querySelector
Typo: addEventListenet -> addEventListener
The repeated id in your HTML are invalid, convert them to class instead.
The function you provide to addEventListener should be anonymous in this case. Giving it a name here serves no purpose other than to waste bytes.
Avoid using inline event handlers, such as onclick, in your HTML code. It's outdated and no longer good practice. Use unobtrusive event handlers instead, such as addEventListener(), which you already use elsewhere in your code.
sort() should compare the a and b arguments and return an integer depending on which way to sort them. In this case, as you're comparing strings you can use localeCompare() on the textContent property of the elements.
After the sort() has completed you need to update the DOM to respect the new order of the elements. To do this you can call append() on the parent element, supplying the children as the argument.
Here's a working example with these issues addressed:
const sortButton = document.querySelector('.sortBtn');
const list = document.querySelector('.list');
const products = list.querySelectorAll('.products');
sortButton.addEventListener('click', () => {
const sortedElements = Array.from(products).sort((a, b) => a.textContent.localeCompare(b.textContent));
list.append(...sortedElements);
})
<div class="list">
<div class="products">Sugar</div>
<div class="products">Banana</div>
<div class="products">Apple</div>
</div>
<button type="button" class="sortBtn">Sort</button>
Convert the children of the parent element to an array. Then you can use the array sort() method to sort it, then append the children back to the parent in that order.
document.querySelector(".sortBtn").addEventListener("click", () => sortDiv(document.querySelector(".list")));
function sortDiv(parent) {
let children = [...parent.children];
children.sort((a, b) => a.innerText.localeCompare(b.innerText));
parent.innerHTML = '';
children.forEach(child => parent.appendChild(child));
}
<div class="list">
<div class="products"> Sugar </div>
<div class="products"> Banana </div>
<div class="products"> Apple </div>
</div>
<button class='sortBtn'>Sort</button>

passing this.id to another function returns null error

I am trying to pass an ID with a function to another function. The console then informs me that there is a TypeError: document.getElementById(...) is null. The javascript file is appended at the end and I also tried adding the code into a self executing function, but that didn't solve the problem.
Basically I would like to an addEventListener to the sub-category divs (buttons) and they should pass their value to another function.
The error is pointing at this line let mainCategory = document.getElementById(recived_value).parentNode.firstChild(this.id); so recived_value is null.
Any help would be welcome. Thank you.
HTML:
<div class="wrapper">
<div class="main-category" id="box">
Boxes
</div>
<div class="sub-category" id="b_small">
Small Boxes
</div>
<div class="sub-category" id="b_medium">
Medium Boxes
</div>
<div class="sub-category" id="b_large">
Large Boxes
</div>
</div>
JS:
var subCategoryClass = document.querySelectorAll(".sub-category");
var subCategoryArray = Array.from(subCategoryClass);
for ( let i = 0; i < subCategoryArray.length; i++ ){
subCategoryArray[i].addEventListener("click", PassValue(this.id));
}
function PassValue(recived_value){
let subCategory = recived_value;
let mainCategory = document.getElementById(recived_value).parentNode.firstChild(this.id);
TwoArgFunc(mainCategory, subCategory);
}
There were a couple of problems. I described them below in // comments.
Edit: Based on your comment, I changed to a normal function definition.
var subCategoryClass = document.querySelectorAll(".sub-category");
var subCategoryArray = Array.from(subCategoryClass);
for ( let i = 0; i < subCategoryArray.length; i++ ){
subCategoryArray[i].addEventListener("click", function(ev) { PassValue(ev.target.id)} ); // need a function here, not just a statement
}
function PassValue(recived_value){
console.log(recived_value);
let subCategory = recived_value;
let mainCategory = document.getElementById(recived_value).parentNode.firstElementChild.id; // use firstElementChild because firstChild is a newline text node
console.log(mainCategory);
// TwoArgFunc(mainCategory, subCategory);
}
<div class="wrapper">
<div class="main-category" id="box">
Boxes
</div>
<div class="sub-category" id="b_small">
Small Boxes
</div>
<div class="sub-category" id="b_medium">
Medium Boxes
</div>
<div class="sub-category" id="b_large">
Large Boxes
</div>
</div>
Above PassValue function put:
var that = this;
And then in your PassValue function pass that.id:
... .firstChild(that.id);

How can I get the data from div already divided

Hi everyone I want to extract data from divs using Jquerys.
So I have this 3 div :
<div class="wind">Venice,it</div>
<div class="wind">Madrid,es</div>
<div class="wind">Rome,it</div>
In my JS file I want to extract: Venice,it / Madrid,es / Rome,it.
What I did for now is: var data = $("div.wind").text() .
Writing this I get the string Venice,itMadrid,esRome,it but I don't want to this. I want the div splitted already like.
var vector= [(Venice,it),(Madrid,es),(Rome,it)]
How can I do this?
Thank you in advance for your help.
Use .each()
$(() => {
var vector = []
$(".wind").each(function(){ vector.push($(this).text()) })
console.log(vector)
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wind">Venice,it</div>
<div class="wind">Madrid,es</div>
<div class="wind">Rome,it</div>
const divs = $("div.wind");
const data = divs.toArray().map(d => d.textContent)
just use push on the innerHTML
var myArray=[];
var div =document.getElementsByTagName('div');
for(let i=0;i<div.length;i++){
myArray.push(div[i].innerHTML);
}
console.log(myArray);
<div class="wind">Venice,it</div>
<div class="wind">Madrid,es</div>
<div class="wind">Rome,it</div>
You can use jQuery's .each to iterate through each div selected. You can then get the .text() value for each div one by one, and push the value into the vector array.
Demo:
var vector = [];
$("div.wind").each(function(index, div) {
var data = $(div).text();
vector.push(data);
});
console.log(vector);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wind">Venice,it</div>
<div class="wind">Madrid,es</div>
<div class="wind">Rome,it</div>

Find next DOM Object that exists in an Array

So, I have created an array of all instances of certain classes.
anchors = [];
$('.a-all').each(function() {
anchors.push($(this));
});
if ( viewport().width > 1366 ) {
sub_anchors = $('.a-lg');
} else if ( viewport().width > 1024 ) {
sub_anchors = $('.a-md');
} else if ( viewport().width > 768 ) {
sub_anchors = $('.a-sm');
} else {
sub_anchors = $('.a-xs');
}
sub_anchors.each(function() {
anchors.push($(this));
});
Then I set a variable 'current' and made it the object with the class '.active'.
current = $('.active');
Now, with jQuery, I want to be able to find the next and previous DOM object relative to .active that exists inside the array I have created.
The array is not in order, and will change at different widths.
Is this possible, or is there a better logic to use here?
EDIT: Adding markup for context.
<div class="website-wrapper w-d-100 h-d-100">
<div class="page-wrapper">
<section id="landing-slider" class="a-all active">
<div class="w-d-100 h-d-100">
This is the homepage landing slider... thing.
</div>
</section>
<section id="about" class="a-all">
<div class="w-d-100 h-d-50 w-sm-75 h-sm-100 dark">
About Panel 1 (75)
</div>
<div class="w-d-100 h-d-50 w-sm-25 h-sm-100">
About Panel 2 (25)
</div>
</section>
<section id="clients" class="a-all">
<div class="w-d-100 h-d-50 w-sm-50 h-sm-100">
Clients Panel 1 (50)
</div>
<div class="w-d-100 h-d-50 w-sm-50 h-sm-100 dark">
Clients Panel 2 (50)
</div>
</section>
<section id="services" class="a-md">
<section class="a-sm">
<div class="w-d-100 h-d-100 w-sm-50 h-sm-100 dark">
Services Panel 1 (50)
</div>
</section>
<section class="a-sm">
<div class="w-d-100 h-d-100 w-sm-50 h-sm-100">
Services Panel 2 (50)
</div>
</section>
</section>
<section id="lets-work" class="a-all">
<div class="w-d-100 h-d-100 dark">
Lets work together! (100)
</div>
</section>
</div>
</div>
Updated answer (now you've shown your HTML)
Since your .a-all elements are siblings (sometimes non-adjacent), you can use prevAll and nextAll, no need for the anchors array at all:
var next = $(".active")..nextAll(".a-all").first();
// or
var previous = $(".active").prevAll(".a-all").first();
If you want to find a .a-md or .a-sm, just use that as the prevAll/nextAll selector.
Original answer
Now, with jQuery, I want to be able to find the next and previous DOM object relative to .active that exists inside the array I have created.
It would be easier if you didn't make an array out of your initial jQuery object. Instead, just remember the object:
var anchors = $(".a-all");
Later, if you want to know where an element is in that array, you can use index(element):
var index = anchors.index($(".active")[0]);
Then you can get the previous like this:
var prev = index > 0 ? anchors.eq(index - 1) : $();
...or the next like this:
var next = index < anchors.length - 1 ? anchors.eq(index + 1) : $();
But if you want to use an array of jQuery instances (like the one you built) instead, you can use findIndex:
var anchors = $(".a-all").map(function() { return $(this); }).get();
// ...
var active = $(".active")[0]; // Note the [0] to get raw element
var index = anchors.findIndex(function(entry) {
return entry[0] === active;
});
// ...
var prev = index > 0 ? anchors[index - 1] : $();
// ...
var next = index < anchors.length - 1 ? anchors[index + 1] : $();

jQuery Concatenate multiple DOM node references into one list

Lets say for example I have the following HTML:
<div class="level0">
<div>level 0 #1</div>
<div class="contents">
<div class="level1">
<div>level 1 #1</div>
<div class="contents">
<div class="level2"><div>level 2 #1</div></div>
</div>
</div>
</div>
</div>
<div class="level0">
<div>level 0 #2</div>
<div class="contents">
<div class="level1"><div>level 1 #2</div></div>
<div class="level1"><div>level 1 #3</div></div>
<div class="level1">
<div>level 1 #4</div>
<div class="contents">
<div class="level2"><div>level 2 #2</div></div>
<div class="level2"><div>level 2 #3</div></div>
</div>
</div>
</div>
</div>
<div class="level0"><div>level 0 #3</div></div>
I want to get all of the references to nodes with class "level0", "level1", or "level2".
Then I want to iterate over them starting with the "level2" references, then going to "level1", then "level0".
For instance, the following code would work for what I am trying to do:
$(".level2").each(function(){
console.log($(this).children().first().text());
});
$(".level1").each(function(){
console.log($(this).children().first().text());
});
$(".level0").each(function(){
console.log($(this).children().first().text());
});
That would make the console output be the following:
level 2 #1
level 2 #2
level 2 #3
level 1 #1
level 1 #2
level 1 #3
level 1 #4
level 0 #1
level 0 #2
level 0 #3
As you can see, they are in order based on class, THEN by order in the HTML from top to bottom. This is what I want
However, I want to store this list of elements in this order so I can just use one loop for all of the elements.
The following code is similar to what I want but displays iterates through the rows in the wrong order.
var $rows = $(".level2, .level1, .level0");
$rows.each(function(){
console.log($(this).children().first().text());
});
This iterates through the rows using in-order traversal.
Is there any way to append these rows into a single variable that I can iterate over in the order I wanted way above?
A rough example using a for loop and _map
var allArr = [],
maxLevel = 2;
for (var i = maxLevel; i > -1; i--) {
var arr = $('.level'+ i ).children('div:first-child').map(function () {
return $.trim($(this).text());
}).get();
allArr = allArr.concat(arr);
}
console.log(allArr);
Needs to be refactored though.
Check Fiddle
I just stumbled upon a working answer looking through a plugins source code.
The solution uses jQuery function $.merge().
The following code accomplishes what I want to do:
var $rows = $(".level2");
var $rows = $.merge($rows,$(".level1"));
var $rows = $.merge($rows,$(".level0"));
$rows.each(function(){
console.log($(this).children().first().text());
});
I supposed if you wanted to get a little more tricky, the following code would also work:
var $allRows = $.merge($.merge($(".level2"),$(".level1")),$(".level0"));
$allRows.each(function(){
console.log($(this).children().first().text());
});
Check out this fiddle to see both options working.

Categories

Resources