Group Selected Elements: document.querySelectorAll - javascript

Hi how can I group my document.querySelectorAll if I have a case like this:
<div>
<p class="flower">Flower 1</p>
<p class="bee">Bee 1</p>
<p class="tree"></p>
</div>
<div>
<p class="flower">Flower 2</p>
<p class="dude"></p>
<p class="snow-leopard"></p>
</div>
<div>
<p class="flower">Flower 3</p>
<p class="tree"></p>
<p class="mountain"></p>
<p class="wizard"></p>
<p class="bee">Bee 3</p>
</div>
I always want to select the flower, if there is a bee I want to have it attached to the flower, I don't care about the rest. The flowers and bees don't have a specific order in the div and there are cases with no bee. Also assume that there is a class at the flower and bee but the rest of the structure isn't as clean as in the example. The only solution I have so far is to go a few levels up and then use regex. At the end I want to include them both into a json:
[{flower: "yellow", bee:"bumblebee"},...]
This approach:
var flowers = document.querySelectorAll(flower);
var bees = document.querySelectorAll(bee);
And then iterating afterwards over the both arrays does not work.

The problem is that you can't really match the flowers with the bees simply with CSS selectors. You need to iterate over all flowers and find the bee sibling if there is one. One way to do this is to get the parent of a flower and then look for bees.
var obj = Array.prototype.map.call(document.querySelectorAll(".flower"), function(f){
var node = {flower: f.textContent};
var bee = f.parentNode.querySelector(".bee");
if (bee) {
node.bee = bee.textContent;
}
return node;
});

Related

Changing html element's position in parent tag when created it with document.createElement

I'm just starting learning Javascript, and right now I'm on document.createElement. I understood that you can create a HTML tag this way, and that afterwards you have to put it into a HTML tag that already exists (parent). My question is Can I choose exactly where I put this created HTML tag in the parent tag ?
Let's say for exemple I have the following HTML :
<div id="parent">
<div>
<p>First paragraph</p>
</div>
<p>Second paragraph</p>
<p>Third paragraph</p>
</div>
And this javascript :
const getMyDiv = document.getElementById("parent");
const createParagraph = document.createElement("p");
getMyDiv.appendChild(createParagraph);
I will have the following result :
<div id="parent">
<div>
<p>First paragraph</p>
</div>
<p>Second paragraph</p>
<p>Third paragraph</p>
<p></p>
</div>
So what i'm asking is how can I create this <p> at a different position, for exemple like this :
<div id="parent">
<div>
<p>First paragraph</p>
</div>
<p>Second paragraph</p>
<p></p>
<p>Third paragraph</p>
</div>
.appendChild(), indeed append your created element at the end of the list of the children of your selected element, as you demonstrated.
Though, there are other methods that can be used, based on your needs, so you can mount your element wherever you want e.g. .insertBefore() or .prepend()
There are some differences on how they work, so I suggest you take a look on the provided links so you can understand the differences.
You can use this script if you want to place the position to a specific location
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<style>
</style>
<script language="javascript">
function myFunction(){
//var getMyDiv = document.getElementById("parent");
//var createParagraph = document.createElement("p");
//getMyDiv.appendChild(createParagraph);
var child = document.createElement('p')
var parent = document.getElementById("parent");
parent.insertChildAtIndex(child, 2)
}
Element.prototype.insertChildAtIndex = function(child, index) {
if (!index) index = 0
if (index >= this.children.length) {
this.appendChild(child)
} else {
this.insertBefore(child, this.children[index])
}
}
</script>
<button onclick="myFunction()">Try it</button>
<div id="parent" style="background-color:red;width=100px;height:100px">
<div>
<p>First paragraph</p>
</div>
<p>Second paragraph</p>
<p>Third paragraph</p>
</div>
to check save as html file and look at the inspection element in the browser

Creating a variable for the text node of each element

I am trying to create a variable for each element in a set. I have an HTML structure like this:
<div id="notes">
<p>Example Text 1</p>
<p>Example Text 2</p>
<p>Example Text 3</p>
</div>
I want to store the text of each of the elements in a separate variable. In this case the elements are dynamically generated, so sometimes there are 2 elements, sometimes there are more.
What I have tried so far:
var $counter= 0;
var variableNote = {};
$('#notes p').each(function(){
$counter += 1;
variableNote["newNote"+$counter] = $("#notes p").text();
console.log(newNote1);
});
What I am doing wrong?
Object properties are not variables. To access them you need to refer to the object.
Also, you're not using the current element of the iteration in your loop.
var variableNote = {};
$('#notes p').each(function(index) {
variableNote["newNote" + (index+1)] = $(this).text();
});
console.log(variableNote["newNote1"]);
This can be achieved by finding the elements and reducing them into a single object.
//lookup the p tags, and reduce them to a single object
var variableNotes = $('#notes p').get().reduce(function(notes, note, index){
notes['newNote'+ ++index] = note.innerText;
return notes;
}, {});
console.log(variableNotes);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="notes">
<p>Example Text 1</p>
<p>Example Text 2</p>
<p>Example Text 3</p>
</div>
var variableNote = {};
$('#notes p').each(
(i,e) => variableNote["newNote" +(i+1)] = $(e).text()
);
console.log( variableNote );
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="notes">
<p>Example Text 1</p>
<p>Example Text 2</p>
<p>Example Text 3</p>
</div>
It can be done using vanilla javascript
var variableNotes = [...document.querySelectorAll("#notes p")].reduce((noteList, note, i)=>{
noteList['newNote'+ (i +1)] = note.innerText;
return noteList;
}, {});
console.log(variableNotes);
<div id="notes">
<p>Example Text 1</p>
<p>Example Text 2</p>
<p>Example Text 3</p>
</div>

Taking the text inside each <p> which is a child node of div and storing inside a array

I am trying to read the content inside paragraph tag which is the child node of div and storing those values into and passing the array to the controller
here is the code:
<div class = "proposal">
<p> one </p>
<p> two </p>
<p> three </p>
<p> three </p>
<p> three </p>
<p> three </p>
</div>
Please help me to get the content of paragraph and store into an array using jquery.
I am trying to get a solution in this way:
var proposal = $("#Proposal").contents().filter(function() {
return this.nodeType === 3;
}) .wrap( "<p></p>" ).end();
I am getting the object but,
for(i=0;i<proposal.length;i++){
proposal = proposal[i].innerHTML
}
giving me the error that,
Cannot read property 'length' of undefined
var arr = $(".proposal p").map(function() {
return $(this).text()
}).get();
console.log(arr)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="proposal">
<p> one </p>
<p> two </p>
<p> three </p>
<p> three </p>
<p> three </p>
<p> three </p>
</div>
Use .map() to add into array.
Use .text() with selector $(".proposal p") -> meaning all child p of element with class proposal
This will get each p and push it into the array.
var data = [];
$(".proposal p").each(function () {
data.push($(this).text());
});

How to get all elements but div (for example), including nested ones?

This is probably a long shot but is there a way to get a collection of elements in JQuery or not without a specific tag/class/id, even the nested ones?
Let's say I have this piece of code:
<div class="container1">
Lorem ipsum dolor sit amet
<br><br>
</div>
<p>This is p 1
<div class="footer">
tessssst
<p>
p test
</p>
</div>
</p>
<div class="container">
tessst
</div>
<p>This is p 2
<div id="someID" class="container">
tessssst 2
</div>
</p>
Now, I'm using JQuery like this, in order to find all but div tags, including descendants:
$('body').find(':not(div, div *)')
In the result collection, I still get the div inside the p elements and I don't want that.
Is there any way to achieve that? I know that this div is part of h1 and since I just want to select elements and not removing or doing DOM manipulations it could be a weird thing to wish for but this is what I need.
The bigger problem - I need to retrieve all text nodes but to exclude some tags/classes/IDs. I'm doing so as suggested here but it's not good enough.
Thanks.
The code you provided seems to work, but maybe you could try this?
$('body').find("*").filter(":not(div)");
There is a jQuery function not(), which removes matching elements from the current set.
So all you need to do is
var nonDivs = $('body').find('*').not('div');
You can do that by first selecting all elements, then selecting <div>s and their descendants, and filtering the "all" results with the "divs" result using .not() (the red style is used to mark the matched set):
var all = $('body').find('*');
var divAll = $('body').find('div, div *');
var nonDiv = all.not(divAll);
nonDiv.css('color', 'red');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container1">
Lorem ipsum dolor sit amet
<br><br>
</div>
<p>This is p 1
<div class="footer">
tessssst
<p>
p test
</p>
</div>
</p>
<div class="container">
tessst
</div>
<p>This is p 2
<div id="someID" class="container">
tessssst 2
</div>
</p>
In the filter function check if it's a text node and also check all of its parents for class, id, tag name - whatever selectors you would like to filter by.
var textnodes = $('body').find("*").contents()
.filter(function () {
return (this.nodeType === 3 && $(this).parents("div").length <= 0);
})
.each(function () {
console.log($(this).text());
});
Here's a working example: https://jsfiddle.net/hracw15o/3/

How to rearrange elements using jQuery?

How to rearrange elements using jQuery ?
Orginal Code :
<p id="paragraph1">1</p>
<p id="paragraph2">2</p>
<p id="paragraph3">3</p>
<p id="paragraph4">4</p>
<p id="paragraph5">5</p>
After Rearrange (put p3 in p2's place)
<p id="paragraph1">1</p>
<p id="paragraph3">3</p>
<p id="paragraph2">2</p>
<p id="paragraph4">4</p>
<p id="paragraph5">5</p>
You can use .insertBefore():
$("#paragraph3").insertBefore("#paragraph2");
Slightly more elaborate example (clicking on a paragraph moves it up):
$("p").click(function() {
$(this).insertBefore($(this).prev());
});
You can test both examples here.

Categories

Resources