How to click svg using querySelector? - javascript

I am trying to build a chrome extension to click an SVG on a webpage using the below command but it shows that "click" is not a function.
Can anyone give me some direction in order to solve this issue?
document.querySelector("div[class^='SubmitChat__SubmitButton']").querySelector("svg > path(0)").click();
<form class="SubmitChat__SubmitChatWrapper-kLTVjd ezNulO">
<div id="PinToTop" style="display: none; border: groove; margin: 5px; padding: 5px;"></div>
<div class="DefaultComments__DefaultCommentsWrapper-drohEF dbvkCO">
<div class="SubmitChat__TextAreaWrapperBox-ijaLYA uQa-DJ">
<textarea data-track-category="Interaction_Comment" data-track-action="click" data-track-name="field_comment" class="SubmitChat__TextAreaWrapper-cEDMAF joGtiU" style="height: 44px;"></textarea>
</div>
<div class="SubmitChat__SubmitButton-kXYuum kSQpDq">
<span class="isvg loaded SubmitChat__SendMessageIcon-hzVurU lcJXRC">
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<path d="M25.305 16.07L7.503 24.307a.802.802 0 01-1.111-.925l1.923-7.493h0L6.392 8.396a.8.8 0 011.111-.925l17.802 8.236a.2.2 0 010 .363zm-16.638-.181h16" fill="none" stroke="#28232D" stroke-linecap="round" stroke-width="1.5">
</path>
</svg>
</span>
</div>
</div>
</form>

You can't really click an svg path but here is a solution:
const pathElem = document.querySelector("div[class^='SubmitChat__SubmitButton'] svg > path")
pathElem.onclick = () => console.log("clicked")
pathElem.dispatchEvent(new Event("click"))
pathElem.dispatchEvent(new Event("click"))
<form class="SubmitChat__SubmitChatWrapper-kLTVjd ezNulO">
<div id="PinToTop" style="display: none; border: groove; margin: 5px; padding: 5px;"></div>
<div class="DefaultComments__DefaultCommentsWrapper-drohEF dbvkCO">
<div class="SubmitChat__TextAreaWrapperBox-ijaLYA uQa-DJ">
<textarea data-track-category="Interaction_Comment" data-track-action="click" data-track-name="field_comment" class="SubmitChat__TextAreaWrapper-cEDMAF joGtiU" style="height: 44px;"></textarea>
</div>
<div class="SubmitChat__SubmitButton-kXYuum kSQpDq">
<span class="isvg loaded SubmitChat__SendMessageIcon-hzVurU lcJXRC">
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<path d="M25.305 16.07L7.503 24.307a.802.802 0 01-1.111-.925l1.923-7.493h0L6.392 8.396a.8.8 0 011.111-.925l17.802 8.236a.2.2 0 010 .363zm-16.638-.181h16" fill="none" stroke="#28232D" stroke-linecap="round" stroke-width="1.5">
</path>
</svg>
</span>
</div>
</div>
</form>
Note that .click() works with HTML but not SVG elements. MDN
Also note that the click event handler in your case is probably not listening on the path element but rather on the svg, div or span tag.

Related

Attach event not working when click on child

I have some dynamically added elements. I want to attach 'click' event on a specific class. But the problem is if I click on the child element it's not working. Here is my dynamically added elements.
<div id="steps">
<div class="step">
<a class="btn step-del">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M12.277 3.763a.9.9 0 010 1.273L9.293 8.018l2.984 2.986a.9.9 0 01-1.273 1.272L8.02 9.291l-2.984 2.985a.9.9 0 01-1.273-1.272l2.984-2.986-2.984-2.982a.9.9 0 011.273-1.273L8.02 6.745l2.984-2.982a.9.9 0 011.273 0z"></path></svg>
</a>
Step 1
</div>
<div class="step">
<a class="btn step-del">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M12.277 3.763a.9.9 0 010 1.273L9.293 8.018l2.984 2.986a.9.9 0 01-1.273 1.272L8.02 9.291l-2.984 2.985a.9.9 0 01-1.273-1.272l2.984-2.986-2.984-2.982a.9.9 0 011.273-1.273L8.02 6.745l2.984-2.982a.9.9 0 011.273 0z"></path></svg>
</a>
Step 2
</div>
</div>
Here is my javascript code:
document.body.addEventListener('click', function (evt) {
if ( evt.target.classList.contains("step-del") ) {
alert(this)
}
}, false);
evt.target is what you click on. You are clicking on a child so it is not going to trigger on a parent. So you would need to look to see if what is clicked on is the element or is a child of that element. You can do that with .closest()
const stepDelElem = evt.target.closest(".step-del");
if (stepDelElem) {
console.log('here');
}
<svg> is a different creature than normal HTML tags. A simple solution is to prevent any mouse events to interact with the <svg> by adding the following to CSS:
svg {
pointer-events: none
}
The other changes are just recommendations.
document.getElementById('steps').addEventListener('click', function(evt) {
if (evt.target.matches(".step-del")) {
console.log(evt.target.className);
}
}, false);
a {
display: inline-block;
width: max-content;
border: 1px solid red
}
svg {
pointer-events: none
}
<div id="steps">
<div class="step">
<a class="btn step-del">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M12.277 3.763a.9.9 0 010 1.273L9.293 8.018l2.984 2.986a.9.9 0 01-1.273 1.272L8.02 9.291l-2.984 2.985a.9.9 0 01-1.273-1.272l2.984-2.986-2.984-2.982a.9.9 0 011.273-1.273L8.02 6.745l2.984-2.982a.9.9 0 011.273 0z"></path></svg>Step
1
</a>
</div>
<div class="step">
<a class="btn step-del">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M12.277 3.763a.9.9 0 010 1.273L9.293 8.018l2.984 2.986a.9.9 0 01-1.273 1.272L8.02 9.291l-2.984 2.985a.9.9 0 01-1.273-1.272l2.984-2.986-2.984-2.982a.9.9 0 011.273-1.273L8.02 6.745l2.984-2.982a.9.9 0 011.273 0z"></path></svg>Step
2
</a>
</div>
</div>
Maybe the target is a child element of the "step-del", so you need to check with closest, which will search for the parent elements if any of them has "step-del" class.
document.body.addEventListener('click', function (evt) {
const del = evt.target.closest(".step-del")
if (del) {
alert(del)
}
}, false);
<div id="steps">
<div class="step">
<a class="btn step-del">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M12.277 3.763a.9.9 0 010 1.273L9.293 8.018l2.984 2.986a.9.9 0 01-1.273 1.272L8.02 9.291l-2.984 2.985a.9.9 0 01-1.273-1.272l2.984-2.986-2.984-2.982a.9.9 0 011.273-1.273L8.02 6.745l2.984-2.982a.9.9 0 011.273 0z"></path></svg>
</a>
Step 1
</div>
<div class="step">
<a class="btn step-del">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M12.277 3.763a.9.9 0 010 1.273L9.293 8.018l2.984 2.986a.9.9 0 01-1.273 1.272L8.02 9.291l-2.984 2.985a.9.9 0 01-1.273-1.272l2.984-2.986-2.984-2.982a.9.9 0 011.273-1.273L8.02 6.745l2.984-2.982a.9.9 0 011.273 0z"></path></svg>
</a>
Step 2
</div>
</div>

object not clickable with selenium

I'm trying to get an object from a table with python and selenium. However, first I need to click in the Goalscorers (table title) to show the table. The problem is that I can't click in any of the object, and there isn't any ref. So I can't understand what I need to do, all this div "are clickable" when I put the mouse on top of them, so not sure how it works, any idea?
I tried
driverBet.find_element(By.XPATH,"//div[contains(#data-test-market,'Goalscorers')]").click()
but it's not clickable, I tried also the data-test-id="rabMarkets" but it's not clickable.
<div data-test-id="rabMarkets">
<div class="_ty4a3m">
<div data-test-id="rabMarketsAccordion">
<div class="_1ufbuwwo ">
<div class="_1b7dz8zNaN">
<div class="_q76d6b">
<span class="_uywwi">
<div>
<div>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24px" height="24px" xmlns:xlink="http://www.w3.org/1999/xlink" role="img" aria-labelledby="title-309" style="fill:#909DB4;height:18px;width:18px;" data-src="//bet.sbgcdn.com/static/assets/7200e23c7ae8f1778ea608e36e92b473.svg" class="injected-svg _uhlm2">
<title id="title-309">
Icon / Toggle / Outlined / Star
</title>
<path fill-rule="nonzero" d="M17.738 20.999a.716.716 0 0 1-.331-.082l-5.408-2.821-5.408 2.821a.717.717 0 0 1-.75-.053.704.704 0 0 1-.284-.692l1.033-5.976-4.375-4.232a.703.703 0 0 1-.18-.725.71.71 0 0 1 .575-.48l6.046-.873L11.36 2.45a.713.713 0 0 1 1.277 0l2.704 5.437 6.046.872a.71.71 0 0 1 .575.481.703.703 0 0 1-.18.725l-4.375 4.232 1.033 5.976a.705.705 0 0 1-.283.692.715.715 0 0 1-.42.135zM5 10l3.5 3.5-1 5 4.499-2.45 4.497 2.45-.996-5L19 10l-4.5-.5c-.155-.022-.988-1.522-2.501-4.5L9.5 9.5 5 10z" role="presentation">
</path>
</svg>
</div>
</div>
</span>
</div>
<div class="_zxe9qt">
<div class="_t0tx82" data-test-market="Goalscorers">Goalscorers</div>
<div class="_1cpli7v"></div></div><div class="_w81afw">
<span class="_uywwi">
<div><div>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 15 9" width="15px" height="9px" xmlns:xlink="http://www.w3.org/1999/xlink" role="img" aria-labelledby="title-1915" style="fill:#909DB4;height:14px;width:14px;" data-src="//bet.sbgcdn.com/static/assets/5c342ef89fd16eb91c0b8ddec4a2dcc0.svg" class="injected-svg _j30eqf _uhlm2">
<title id="title-1915">
icon-arrow-down
</title>
<path transform="translate(7.250000, 5.000000) scale(1, -1) rotate(90.000000) translate(-7.250000, -5.000000)" fill-rule="evenodd" d="m3 5.0033l7-7.0033 0.79289 0.79289c0.39023 0.39065 0.39032 1.0237 2.119e-4 1.4144l-4.7931 4.796 4.7927 4.7898c0.39085 0.3902 0.39104 1.0234 6.357e-4 1.414-7.06e-5 7.07e-5 -1.412e-4 1.413e-4 -4.238e-4 1e-7l-0.79289 0.79289-7-6.9967z" role="presentation"></path>
</svg></div></div></span></div></div></div></div></div></div>
thank you
You can access the element using the class, something like this:
This functions first check if the element with the class exists:
def check_exists_by_class_name(browser, classname):
try:
browser.find_element(By.CLASS_NAME, classname)
except NoSuchElementException:
return False
return True
Then, just use the function:
browser = webdriver.Chrome(service=service, options=options)
if check_exists_by_class_name(browser, '_t0tx82'):
print('Go on')
else:
print('not found')

how to play two audio files with same id with javascript

i have two audio files with progress bar and both having same id:
<audio id="player" src="<?=base_url('mp3/'.$rec->file)?>"></audio>
</p>
<button class="btn btn-success btn-sm" id="play">
<svg style='font-size: 1.3em' class="bi bi-play-fill" width="1em" height="1em"
viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path d="M11.596 8.697l-6.363 3.692c-.54.313-1.233-.066-1.233-.697V4.308c0-.63.692-1.01 1.233-.696l6.363 3.692a.802.802 0 010 1.393z"/>
</svg>
</button>
<button class="btn btn-secondary btn-sm" id="pause">
<svg style='font-size: 1.3em' class="bi bi-pause-fill" width="1em" height="1em" viewBox="0 0 16 16"
fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path d="M5.5 3.5A1.5 1.5 0 017 5v6a1.5 1.5 0 01-3 0V5a1.5 1.5 0 011.5-1.5zm5 0A1.5 1.5 0 0112 5v6a1.5 1.5 0 01-3 0V5a1.5 1.5 0 011.5-1.5z"/>
</svg>
</button>
<progress style="height: 4px;border: none;width: 300px;max-width: 330px" id="seekbar" value="0" max="1">ssss
And Here's js
<script type="text/javascript">
$('#play').on('click', function() {
document.getElementById('player'.).play();
});
$('#pause').on('click', function() {
document.getElementById('player').pause();
});
$('#player').on('timeupdate', function() {
$('#seekbar').attr("value", this.currentTime / this.duration);
});
</script>
now i am able to play the first audio file but cannot play second file
how do i do that?????
if there's any other solution like looping ids or anything just tell me because i am a noob in js
document.getElementById only returns the first match, if you want to get all matches, use
document.querySelectorAll instead.
Here's how you should do it
$('#play').on('click', function() {
[...document.querySelectorAll('#player')].forEach(e => e.play());
});
$('#pause').on('click', function() {
[...document.querySelectorAll('#player')].forEach(e => e.pause());
});
As kerbholz mentioned, id should be unique. If it meant to have multiple instances, consider to use class instead.

Jquery onclick method is not working properly

I'm trying to make a search form. I want it to be like when I click in the search form opener button, the search form would show and its width would be 100%.
When I click it again the search form width would return to 0. The first one is working but when I click it back, the form is not set to width of 0.
app.js :
var header_right_search_btn =$("#header_right_search_btn");
var header_search_cont = $("#header_search_cont");
var search_box = $("#search_box");
header_right_search_btn.click(function(e){
e.preventDefault();
if(header_search_cont.css("width","0")){
header_search_cont.css("width","100%")
search_box.focus();
header_search_cont.css("opacity","1");
header_search_cont.css("transition","all .2s ease-in-out");
}else if(header_search_cont.css("width","100%")){
header_search_cont.css("width","0")
header_search_cont.css("opacity","0");
header_search_cont.css("transition","all .2s");
}
console.log("hhihihihi");
})
var search_area_die = $("#search_area_die");
search_area_die.click(function(e){
e.preventDefault();
header_search_cont.css("width","0")
header_search_cont.css("opacity","0");
header_search_cont.css("transition","all .2s");
})
//search ends
<div id="header_search_cont" class="unstreched_search">
<form action="" method="post" name="search_form" id="search_form" enctype="multipart/form-data">
<button type="button" id="search_area_die"><svg id="search_die_svg" version="1.1" id="Layer_1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
<g>
<g>
<path
d="M501.333,245.333H36.417l141.792-141.792c4.167-4.167,4.167-10.917,0-15.083c-4.167-4.167-10.917-4.167-15.083,0l-160,160c-4.167,4.167-4.167,10.917,0,15.083l160,160c2.083,2.083,4.813,3.125,7.542,3.125c2.729,0,5.458-1.042,7.542-3.125c4.167-4.167,4.167-10.917,0-15.083L36.417,266.667h464.917c5.896,0,10.667-4.771,10.667-10.667S507.229,245.333,501.333,245.333z" />
</g>
</g>
</svg></button>
<input type="search" name="search_box" id="search_box" placeholder="Search..."><button id="searchbtn"
name="searchbtn"><svg class="search_ico_svg" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 512 512"
style="enable-background:new 0 0 512 512;" xml:space="preserve">
<g>
<g>
<path d="M508.875,493.792L353.089,338.005c32.358-35.927,52.245-83.296,52.245-135.339C405.333,90.917,314.417,0,202.667,0S0,90.917,0,202.667s90.917,202.667,202.667,202.667c52.043,0,99.411-19.887,135.339-52.245l155.786,155.786c2.083,2.083,4.813,3.125,7.542,3.125c2.729,0,5.458-1.042,7.542-3.125C513.042,504.708,513.042,497.958,508.875,493.792zM202.667,384c-99.979,0-181.333-81.344-181.333-181.333S102.688,21.333,202.667,21.333S384,102.677,384,202.667
S302.646,384,202.667,384z" />
</g>
</g>
</svg></button></form>
</div>
Simple way is to use addClass() and removeClass() functions instead of using .css Then for if statement you can use if($(selector).hasClass())
var header_right_search_btn =$("#header_right_search_btn");
var header_search_cont = $("#header_search_cont");
var search_box = $("#search_box");
header_right_search_btn.click(function(e){
e.preventDefault();
if(!header_search_cont.hasClass('strech')){ //<< if not hasClass() strech
search_box.focus();
header_search_cont.addClass('strech'); // addClass()
}else{
header_search_cont.removeClass('strech'); // removeClass()
}
console.log("hhihihihi");
})
var search_area_die = $("#search_area_die");
search_area_die.click(function(e){
e.preventDefault();
header_search_cont.removeClass('strech'); //<< removeClass()
})
//search ends
#header_search_cont{
width : 0px;
opacity : 0;
transition : all .2s ease-in-out;
overflow : hidden;
background : red;
padding : 10px;
box-sizing : border-box;
}
#header_search_cont.strech{
width : 100%;
opacity : 1;
transition : all .2s ease-in-out;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="header_right_search_btn">Open Search</div>
<div id="header_search_cont">
<form>
<input id="search_box" type="search" placeholder="search" />
<input id="search_area_die" type="submit" value="search"/>
</form>
</div>
Explanation:
Add/remove class strech to the element on click
Check for strech class by using .hasclass('strech')) . The ! mark means NOT so !$(selector).hasClass('strech') means if the element doesn't have this class

How to get parent object ID when clicking on ellipse element?

If I'm interpreting correct hierarchy of elements, what I'm wanting to do would be ...
That element <ellipse> children of <svg>, <object> and <div id="svg_*"> when clicked showed me the id of your <object> parent.
this * is because the <ellipse> will be from your respective svg div.
This is how my HTML strtucture is, thoses #DOCUMENT are window.frames opened by each <object> tag.
<body>
<div id="content">
<div class="header"></div>
<nav class="nav"></nav>
<div class="div 1"></div>
<div class="div 2">
<div id="svg_1">
<object id="OneNameObject" data="../folder/fileOne.svg">
#DOCUMENT
<svg>
<ellipse>I have one addEventerLinster Click here</ellipse>
</svg>
</object>
</div>
<div id="svg_2">
<object id="TwoNameObject" data="../folder/fileTwo.svg">
#DOCUMENT
<svg>
<ellipse>I have one addEventerLinster Click here</ellipse>
</svg>
</object>
</div>
</div>
<div class="div 3"></div>
<div class="div 4"></div>
</div>
For now I'm getting access to the <object> id when I specify the index of it to be used.
0 for svg_1 #document
1 for svg_2 #document
So I thought I'd use the this selector to call the ellipse hireararchy. But I could not, and i don't know how.
something like :
this.parent.document.querySelector('object').id;
This is the way i getting the id using index, and by this - for sure - i aways get the id from selected <object>.
window.onload = function (){
//This is for addEventLinster on each <ellipse>.
var obj = document.querySelectorAll('object');
for (var x = 0; x < obj.length; x++){
var svg = obj[x].contentDocument.querySelector('svg');
var e = svg.querySelectorAll('ellipse');
for ( var i = 0; i < e.length; i++){
e[i].addEventListener('click', function(){
var objId = parent.document.getElementsByTagName('object')[0].id;
alert( objId );
});
}
}
};
Working Example \ but not functional on my context.
This code is working, but it's not on my context ! Need to get that info, I am using <object> data attr to load svg files, they come on embed tags with a new window frame and a new document page. That is why i cant get they elements so easy.
Image HTML Code / DOM painel - * detail : ellipses is on <g> tag.
$(document).ready(function(){
var obj = $('ellipse');
obj.on('click', function(){
alert($(this).parents('object').attr('id'));
});
});
div {
width: 52px;
margin: 2px;
border-radius: 10%;
}
#svg_1:hover, #svg_2:hover {
opacity: 0.7;
}
#svg_1 {
border: 2px solid indianred;
}
#svg_2 {
border: 2px solid lightblue;
}
<html>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
<div id="content">
<div class="header"></div>
<nav class="nav"></nav>
<div class="div 1"></div>
<div class="div 2">
<div id="svg_1">
<object id="redObject" data="">
<!-- #DOCUMENT -->
<svg width="50" height="48" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
<ellipse ry="14" rx="13" id="svg_2" cy="25" cx="25" stroke-linecap="null" stroke-linejoin="null" stroke-dasharray="null" stroke-width="0" stroke="#cd5c5c" fill="#bf2a2a"/>
</svg>
</object>
</div>
<div id="svg_2">
<object id="blueObject" data="">
<!-- #DOCUMENT -->
<svg width="50" height="50" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
<ellipse ry="14" rx="13" id="svg_2" cy="25" cx="25" stroke-linecap="null" stroke-linejoin="null" stroke-dasharray="null" stroke-width="0" stroke="#c95c5c" fill="#56aaff"/>
</svg>
</object>
</div>
</div>
<div class="div 3"></div>
<div class="div 4"></div>
</div>
</body>
</html>
ps; I found the title of the question a bit confusing, in case someone has a better suggestion, I would appreciate it!
Give the below a try. (Not a tested code but should ideally work unless some syntax issues or so)
We can check if something can unnecessary can be removed.
$.each($('[id^="svg_"]'),function(){
var eclipse = $(this).find("object").find('svg').find('ellipse');
console.log(eclipse)
$(eclipse).click(function (){
alert($(this).parent().parent().attr('id'))
})
});

Categories