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>
Related
This question already has answers here:
What is the pure JavaScript equivalent of jQuery's .parents() method? [duplicate]
(2 answers)
Closed 7 months ago.
A question:
How to find out which parent contains an attribute?
Example:
<div custom-attribute>
<div>
<div>
<div>
<div><p>some text</p></div>
</div>
</div>
</div>
</div>
I can't know exactly where this attribute will be applied and on which element.
I need to iterate through all the parents from the <p> element.
Without jquery
Use a while loop to iterate the parents until you find the parent that has the attribute:
const elem = document.getElementById('elem');
let parent = elem.parentElement;
while (parent && !parent.hasAttribute('custom-attribute')) {
parent = parent.parentElement;
}
if (parent) {
console.log(parent);
}
<div custom-attribute>
<div>
<div>
<div>
<div>
<p id="elem">some text</p>
</div>
</div>
</div>
</div>
</div>
const elem = document.querySelector('#elem');
const list = Array.from(document.querySelectorAll('[custom-attribute]'));
const parent = list.find(item => item.contains(elem));
// ...
If you may have not only one parent that has the custom-attribute, you'd better loop as you mentioned in question.
I have searched at numerous places but I am not getting an answer
here is my html :
<form id="search_form_homepage" >
...
<div class="search__autocomplete" style="display: block;">
<div class="acp-wrap js-acp-wrap">
<div class="acp" data-index="0"><span class="t-normal">elephant</span>cheap auto</div>
<div class="acp" data-index="1"><span class="t-normal">elephant</span>asia</div>
...
...
<div class="acp" data-index="2"><span class="t-normal">elephant</span>africa</div>
</div>
...
</div>
</form>
I simply need to get the count of the <div> present within the div with class acp-wrap js-acp-wrap
I can reach this point but am stuck beyond :
let xyz = driver.findElements(By.className(".acp-wrap js-acp-wrap>div"));
You would need to use By.css to get element by this: .acp-wrap js-acp-wrap > div. Also, your selector is not correct. When you select an element by class, you need to put a period before the class name: .acp-wrap.js-acp-wrap > div (remove the space between acp-wrap and js-acp-wrap, too).
Here is how you can get that element now:
let xyz = driver.findElements(By.css(".acp-wrap.js-acp-wrap > div"));
Now to get the count, you can get the length property of xyz. But since driver.findElement returns a promise, you need to use async-await. You can create a function:
async function getCount() {
let xyz = await driver.findElements(By.css(".acp-wrap.js-acp-wrap > div"));
const count = xyz.length;
return count;
}
EDIT
When you call the function:
getCount().then(function(count) {
// your stuff there
});
I would like to change the style, if there is a specific class on the page,
but it doesn't work. what is wrong with below code snippet?
https://jsfiddle.net/1wc0xdor/
<html>
<body>
<div id='category'>
<div id="search_filters_wrapper">
Filter
</div>
<div class="st_banner_row" style="">
There is Banner
</div>
</div>
</body>
</html>
<script>
var elementExists = document.getElementById('category').getElementsByClassName('st_banner_row');
if (typeof(elementExists) != 'undefined' && elementExists != null)
{
$("#search_filters_wrapper").css({
margin-top: 40,
});
}
</script>
document.getElementsByClassName returns a NodeList. If the class isn't found, it will return an empty list, not null.
Check the length rather than whether it's null.
Also, margin-top is not a valid identifier, you need to quote it to use it as an object key (or you can change to camelCase marginTop:)
if (elementExists.length != 0) {
$("#search_filters_wrapper").css({
"margin-top": 40,
});
}
getElementsByClassName always returns a NodeList (think, array), so elementExists always... exists. So you really only need to check if the array isn't empty to be sure that your target class exists. Further, rather than calling getElementById first, you really only need to call getElementsByClassName, unless you're specifically looking for this class within the scope of the parent element with that id.
If you do need to search within the scope of the parent element with that id, consider using querySelectorAll with an appropriate CSS selector
const elements = document.querySelectorAll('#category .st_banner_row');
if (elements.length) {
$('#search_filters_wrapper').css({
'margin-top': 40
});
}
Also, consider setting a CSS class here rather than programmatically setting the css attribute directly, as the latter is bad practice unless it can't be helped.
Answer:
When you check if the element exists you are actually looking at an Array. To determine if the Array is not empty, and therefore, the class exists within the category element, you just need to test the length property.
If the Array length is 0 and nothing is in it, it will return false. If the Array length is greater than 0, something is in it, and it will return true.
Secondly when you utilize properties that have a hyphen( - ) you need to pass that property as a String within the object you're passing to the css method of JQuery's element wrapper.
var elementExists = document.getElementById('category')
.getElementsByClassName('st_banner_row')
.length;
if (elementExists)
{
$("#search_filters_wrapper").css({"margin-top": 40});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id='category'>
<span>Below is 40px</span>
<div id="search_filters_wrapper">
Filter
</div>
<div class="st_banner_row" style="">
There is Banner
</div>
</div>
Aside:
It's odd that you're using JQuery for this one aspect of code. It would be easier and more maintainable to use either all Vanilla JavaScript or all JQuery.
JQuery:
var elementExists = $("#category").find(".st_banner_row").length;
if (elementExists)
{
$("#search_filters_wrapper").css({"margin-top": 40});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id='category'>
<span>Below is 40px</span>
<div id="search_filters_wrapper">
Filter
</div>
<div class="st_banner_row" style="">
There is Banner
</div>
</div>
JavaScript:
var elementExists = document.getElementById('category')
.getElementsByClassName('st_banner_row')
.length;
if (elementExists)
{
document.getElementById("search_filters_wrapper").style.marginTop = "40px";
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id='category'>
<span>Below is 40px</span>
<div id="search_filters_wrapper">
Filter
</div>
<div class="st_banner_row" style="">
There is Banner
</div>
</div>
Alternative Vanilla JS using querySelector:
var elementExists = document.querySelector('#category .st_banner_row');
if (elementExists)
{
document.querySelector("#search_filters_wrapper").style.marginTop = "40px";
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id='category'>
<span>Below is 40px</span>
<div id="search_filters_wrapper">
Filter
</div>
<div class="st_banner_row" style="">
There is Banner
</div>
</div>
Note In this version we don't need to check the length because if category does not have a child with a class of st_banner_row the selector will return undefined.
Alternative Vanilla JavaScript Functional example:
// helper functions
const el = ( query, context = document ) => context.querySelector( query ),
elementExists = query => Boolean( el( query ) ),
ifElementExists = ( query, fn = () => undefined ) => elementExists( query ) && fn(),
elStyle = query => ( prop, value ) => el( query ).style[ prop ] = value,
changeStyle = query => ( prop, value ) => () => elStyle( query )( prop, value );
// execution
ifElementExists( "#category .st_banner_row",
changeStyle( "#search_filters_wrapper" )( "margin-top", "40px" )
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id='category'>
<span>Below is 40px</span>
<div id="search_filters_wrapper">
Filter
</div>
<div class="st_banner_row" style="">
There is Banner
</div>
</div>
I tried it with getElementById and it worked. But now I want the same with multiple div's so I have to use classes. So I changed the method to getElementsByClassName and now it says undefined.
(The function is called when a option in a select changes. This works correctly)
HTML:
<div class="item_content">
<h3 class="filmnaam">22 jump street</h3>
</div>
<div class="item_content">
<h3 class="filmnaam">rio 2</h3>
</div>
Javascript:
function sorting(sortingway) {
alert(sortingway.value);
var titelfilms = document.getElementsByClassName("filmnaam");
var titels = titelfilms.innerHTML;
console.log(titels[0]);
}
Is there a way to do this without jQuery?
getElementsByClassName returns a collection, so loop that!
var titelfilms = document.getElementsByClassName("filmnaam");
for (var i = 0; i < titelfilms.length; i++) {
var titels = titelfilms[i].innerHTML;
console.log(titels);
}
titelfilms is a node list, you can't get the innerHTML of a node list as a whole, it contains multiple references to elements which each have their own individual property.
You could loop through and concatenate each innerHTML onto a variable, or you could map() the innerHTML of your returned elements to an array and then join() them up:
function sorting(sortingway) {
var titelfilms = document.getElementsByClassName("filmnaam");
var titels = Array.prototype.map.call(titelfilms, function (el) {
return el.innerHTML;
}).join(' ');
console.log(titels);
}
sorting();
<div class="item_content">
<h3 class="filmnaam">22 jump street</h3>
</div>
<div class="item_content">
<h3 class="filmnaam">rio 2</h3>
</div>
<div class="contain_questions">
<div class="question">
<div class="question_text">First question</div>
<div class="question_mandatory">1</div>
<div class="options">
<div class="option"><div class="option_name">a</div><div class="option_value">1</div></div>
<div class="option"><div class="option_name">b</div><div class="option_value">2</div></div>
<div class="option"><div class="option_name">c</div><div class="option_value">3</div></div>
</div>
add_another_option
</div>
.
. // many more div.question ...
.
<input type="button" value="submit_questions" />
</div>
How do you use .each() for each div.option within an outer .each() for each question?
I have the outer .each() working fine, which iterates over all div.question and pushes the question_text etc into an array, however I cant seem to target the options container within each question in order to also push all of the options for each question into the array.
Also, is it possible to target a subset of the DOM with the .each() function, or is there some other way to iterate over all classes within a given class?
Thanks guys..
Just as simple as that:
$(".question").each(function() {
...
$(this).find(".option").each(function() {
...
});
});
So your code might look like the following:
var questions = [];
$(".question").each(function() {
var obj = {
name : $(this).find(".question_text").text(),
options : []
};
$(this).find(".option").each(function() {
obj.options.push({
name : $(this).find(".option_name").text(),
value : $(this).find(".option_value").text()
});
});
questions.push(obj);
});
console.log(questions);