Get element by classname inside certain div - javascript

I am trying to click some buttons in a page which has this html code
<div class="a">
<span>
<a class="b" role="button">test</a>
</span>
</div>
So what i've tried is to take ONLY the div's class a
var buttons = document.getElementsByClassName('a').getElementsByClassName('b');
for(var i = 0; i <= buttons.length; i++)
buttons[i].click();
Is there anyway to get the button with class name b but Only the one that is inside the div with class name a ??
P.S. i have also tried and this
var buttons = document.getElementsByClassName('a').getElementsByTagName('span').getElementsByClassName('b');
for(var i = 0; i <= buttons.length; i++)
buttons[i].click();
But i get an empty array [ ] as a response when I console.log(buttons)

You can use querySelector to overcome the issue.
document.querySelectorAll("div.a a.b");

You can use jquery and do
var buttons = $('.a > .b');

Here's an XPath solution:
let res = document.evaluate('//*[#class="a"]//*[#class="b"]',document,null,XPathResult.ANY_TYPE,null);
res.iterateNext().click();
<div class="a">
<span>
<a class="b" role="button" onclick="console.log('clicked!')">test</a>
</span>
</div>
Unfortunately Internet Explorer still doesn't support the XPath API.

Since only one div will be assigned the class='a', you can either supply an ID instead, or, you can do this :
var spans = document.getElementsByClassName('a')[0].getElementsByTagName('span');
// [0] indicates the first element with the class='a'
for(var i = 0; i < spans.length; i++) {
spans[i].getElementsByClassName('b')[0].click();
}
<div class="a">
<span>
<a class="b" role="button" href="javascript:void(0)" onclick="console.log(this.innerHTML+' was clicked !')">test 1</a>
</span>
<span>
<a class="b" role="button" href="javascript:void(0)" onclick="console.log(this.innerHTML+' was clicked !')">test 2</a>
</span>
<span>
<a class="b" role="button" href="javascript:void(0)" onclick="console.log(this.innerHTML+' was clicked !')">test 3</a>
</span>
</div>
This works perfectly, here it is : https://jsfiddle.net/nd8m7mms/4/

Related

How to make this code work with .each function?

I have the following piece of code in a script tag that I need to get working for all #tel ID elements on the page. I can only get it to work for the first #tel element. I've been trying to use .each function - but no luck...
The reason being is that I can't seem to get the ACF repeater URL to suit my needs here. The Advanced section of the dynamic content link part is not displaying. So I am trying to make a hack in an HTML widget for this.
But I need it to work for all buttons with button ID #tel.
Here's the code:
var link = document.getElementById('tel');
var href = link.getAttribute('href');
link.setAttribute('href', href.replace('http://', 'tel:'));
<div class="elementor-button-wrapper">
<a href="http://44400907" class="elementor-button-link elementor-button elementor-size-xs" role="button" id="tel">
<span class="elementor-button-content-wrapper">
<span class="elementor-button-text elementor-inline-editing" data-elementor-setting-key="text" data-elementor-inline-editing-toolbar="none">
44 40 09 07
</span>
</span>
</a>
</div>
In HTML/javascript element IDs must be unique. So in your case you can use class for that:
var links = document.querySelectorAll('.tel');
for(let i = 0; i < links.length; i++)
{
let link = links[i];
var href = link.getAttribute('href');
link.setAttribute('href', href.replace('http://', 'tel:'));
}
<div class="elementor-button-wrapper">
<a href="http://44400907" class="elementor-button-link elementor-button elementor-size-xs tel" role="button">
<span class="elementor-button-content-wrapper">
<span class="elementor-button-text elementor-inline-editing" data-elementor-setting-key="text" data-elementor-inline-editing-toolbar="none">44 40 09 07</span>
</span>
</a>
</div>
<div class="elementor-button-wrapper">
<a href="http://44400908" class="elementor-button-link elementor-button elementor-size-xs tel" role="button">
<span class="elementor-button-content-wrapper">
<span class="elementor-button-text elementor-inline-editing" data-elementor-setting-key="text" data-elementor-inline-editing-toolbar="none">44 40 09 08</span>
</span>
</a>
</div>
<div class="elementor-button-wrapper">
<a href="http://44400909" class="elementor-button-link elementor-button elementor-size-xs tel" role="button">
<span class="elementor-button-content-wrapper">
<span class="elementor-button-text elementor-inline-editing" data-elementor-setting-key="text" data-elementor-inline-editing-toolbar="none">44 40 09 09</span>
</span>
</a>
</div>

How do I hide a div if there's a certain string of text on another element?

I'm trying to only show class="important" whenever certain text/products like 'KR-KJSC-MICROBIT' and 'KR-KJSC-D' are on the page. When those texts are not on the page then this element should be hidden. Can anyone please assist me with this?
<div class="important">SHOW IF CERTAIN PRODUCTS ARE IN THE CART/THANK YOU PAGE</div>
<div class="cart-line-product-info>
<span class="cart-product-code">
<a class="product-code">Code: KR0KJSC-MICROBIT</a>
</span>
</div>
<div class="cart-line-product-info>
<span class="cart-product-code">
<a class="product-code">Code: KR-KJSC-D</a>
</span>
</div>
You can set a variable with the specific words you want to match.
Get html elements.
Iterates throught the product codes (anchors).
If words array includes the textContent of an anchor element, then display the importants elements:
let words = ['KR0KJSC-MICROBIT', 'KR-KJSC-D']
let anchors = document.querySelectorAll(".product-code")
let importants = document.querySelectorAll(".important");
for(let i = 0; i < anchors.length; i++){
if(words.includes(anchors[i].textContent.replace('Code: ', ''))){
importants.forEach(x => x.style.display = 'block')
} else {
importants.forEach(x => x.style.display = 'none')
}
}
<div class="important">SHOW IF CERTAIN PRODUCTS ARE IN THE CART/THANK YOU PAGE</div>
<div class="cart-line-product-info">
<span class="cart-product-code">
<a class="product-code">Code: KR0KJSC-MICROBIT</a>
</span>
</div>
<div class="cart-line-product-info">
<span class="cart-product-code">
<a class="product-code">Code: KR-KJSC-D</a>
</span>
</div>
Here is a way to do it. Not really the best solution but will work if you add the js script at end of page.
const codeElements = document.querySelectorAll(".product-code");
let codes = []
codeElements.forEach( element => codes.push(element.innerHTML))
if(!codes.includes("Code: KR-KJSC-D")) {
document.querySelector(".important").style.display = "none"
}
<div class="important">SHOW IF CERTAIN PRODUCTS ARE IN THE CART/THANK YOU PAGE</div>
<div class="cart-line-product-info>
<span class="cart-product-code">
<a class="product-code">Code: KR0KJSC-MICROBIT</a>
</span>
</div>
<div class="cart-line-product-info>
<span class="cart-product-code">
<a class="product-code">Code: KR-KJSC-D</a>
</span>
</div>
let pageSource = document.documentElement.innerHTML
// regex match for target strings against page source
if(pageSource.match(/KR0KJSC-MICROBIT|KR-KJSC-D/g)){
$('.important').show()
}

How do i get an element to detect mouse hover

The HTML is too long. The full. is the only part that really matters
var buttons = document.getElementsByTagName('button');
for (i = 0; i < buttons.length; i++) {
console.log(buttons[i])
buttons[i].onmouseenter = function() {
console.log('hello')
}
}
<div id='buttons'>
<a href='https://discord.com/api/oauth2/authorize?client_id=775316623220277248&permissions=391232&scope=bot' target='_blank'>
<button id='invbutton'><i class="fab fa-discord fa-3x"></i>Invite</button>
</a>
<button>Support</button>
</div>
I have defined the script tag at the end of the HTML file. I have also tried adding event listeners which did not work. However, the 'hello' is console logged when the button is pressed for some reason
You've simply forgotten the closing curly bracket of the for loop.
var buttons = document.getElementsByTagName('button');
for (i = 0; i < buttons.length; i++) {
console.log(buttons[i])
buttons[i].onmouseenter = function() {
console.log('hello')
}
} //This curly bracket was missing in your code!
<div id='buttons'>
<a href='https://discord.com/api/oauth2/authorize?client_id=775316623220277248&permissions=391232&scope=bot' target='_blank'>
<button id='invbutton'><i class="fab fa-discord fa-3x"></i>Invite</button>
</a>
<button>Support</button>
</div>
use onmouseover event.
<button onmouseover="handleHover()">Support</button>
var buttons = document.getElementsByTagName('button');
function handleHover() {
console.log('Hovered');
}
<div id='buttons'>
<a href='https://discord.com/api/oauth2/authorize?client_id=775316623220277248&permissions=391232&scope=bot' target='_blank'>
<button id='invbutton'><i class="fab fa-discord fa-3x"></i>Invite</button>
</a>
<button onmouseover="handleHover()">Support</button>
</div>

Replace innerHTML with attribute value for each element with class

Please consider this HTML:
<a class="title" threedots="Product Name 1"></a>
<a class="title" threedots="Product Name 2"></a>
<a class="title" threedots="Product Name 3"></a>
I want to change it to this:
<a class="title" threedots="Product Name 1">Product Name 1</a>
<a class="title" threedots="Product Name 2">Product Name 2</a>
<a class="title" threedots="Product Name 3">Product Name 3</a>
using JavaScript or jQuery. I can change the first occurrence only with this:
var fullName = document.getElementsByClassName("title")[0].getAttribute("threedots");
document.getElementsByClassName("title")[0].innerHTML = fullName;
But I need help writing a script that can change all of the occurrences. I have researched foreach and HTMLcollection, but I don't understand them. Can someone point me in the right direction for writing a script that will find each <a class="title"> and grab the value for its threedots attribute and inject it in?
You could simply select all the elements by their [threedots] attribute and class name, then iterate over them using a simple for loop:
var elements = document.querySelectorAll('.title[threedots]');
for (var i = 0; i < elements.length; i++) {
elements[i].textContent = elements[i].getAttribute('threedots');
}
Or using .forEach():
var elements = document.querySelectorAll('.title[threedots]');
Array.prototype.forEach.call(elements, function (el) {
el.textContent = el.getAttribute('threedots');
});
As a side note, since you're only changing text, you can use the .textContent property rather than .innerHTML. In addition, threedots isn't a valid attribute. Consider using a data-* attribute such as data-threedots:
<a class="title" data-threedots="Product Name 1"></a>
<a class="title" data-threedots="Product Name 2"></a>
<a class="title" data-threedots="Product Name 3"></a>
Then you can access the the property .dataset.threedots:
var elements = document.querySelectorAll('.title[data-threedots]');
for (var i = 0; i < elements.length; i++) {
elements[i].textContent = elements[i].dataset.threedots;
}
Since you mentioned jQuery, you could also use the following:
$('.title[data-threedots]').text(function () {
return $(this).attr('data-threedots');
});
So instead of only using the first index of document.getElementsByClassName("title") we can iterate it.
var titles = document.getElementsByClassName("title");
for(var i = 0; i < titles.length; i++) {
var title = titles[i];
title.innerHTML = title.getAttribute("threedots");
}
a {
display: block;
}
<a class="title" threedots="Product Name 1"></a>
<a class="title" threedots="Product Name 2"></a>
<a class="title" threedots="Product Name 3"></a>
You select all anchor elements using jQuery and set it.
$('a').each(function(){
$(this).html($(this).attr('threedots'));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a class="title" threedots="Product Name 1"></a>
<a class="title" threedots="Product Name 2"></a>
<a class="title" threedots="Product Name 3"></a>

How can Javascript capture these values?

Let's say I have a webpage that has this in it:
<a href="https://www.youtube.com/analytics?vmv=2#fi=v-FLp5ViIYS7s" class="yt-uix-tooltip" title="View stats">
<span class="vm-video-metric video-view-count">
<span>
<span class="vm-video-metric-icon">
<img src="//s.ytimg.com/yt/img/pixel-vfl3z5WfW.gif" alt="">
</span>
<span class="vm-video-metric-value">
1,644
</span>
</span>
</span>
<span class="vm-video-metric video-likes-count">
<span>
<span class="vm-video-metric-icon">
<img src="//s.ytimg.com/yt/img/pixel-vfl3z5WfW.gif" alt="">
</span>
<span class="vm-video-metric-value">
13
</span>
</span>
</span>
<span class="vm-video-metric video-dislikes-count">
<span>
<span class="vm-video-metric-icon">
<img src="//s.ytimg.com/yt/img/pixel-vfl3z5WfW.gif" alt="">
</span>
<span class="vm-video-metric-value">
3
</span>
</span>
</span>
I would like to capture the three values encapsulated by the <span class="vm-video-metric-value"></span> tags.
In Javascript, this would normally be done using the id tag. But since there is no id tag, how can these values be captured?
Use the getElementsByClassName method, like so.
var elements = document.getElementsByClassName("vm-video-metric-value");
for (var i = 0; i < elements.length; i++) {
console.log(elements[i].innerHTML);
}
var qsa = document.querySelectorAll("span.vm-video-metric-value"), l = qsa.length, i;
var vals = [];
for( i=0; i<l; i++)
vals.push(parseInt(qsa[i].firstChild.nodeValue.replace(/[^0-9]/g,''),10));
vals is now an array containing the numbers you wanted extracted. Requires a browser capable of querySelectorAll, which almost all are (IE7 and down are not).
If you're using jQuery, and you should! It's really simple to learn and it will take you a week tops to start using it:
$('span.vm-video-metric-value').each(function() {
console.log($(this).text());
});
"For each span with class vm-video-metric-value, print the text inside to the console."
Easy as pie!
Please give jQuery a shot, it's a great library.

Categories