XPath - Select element which has an exact number of specific sub-node - xpath

Let's take this HTML:
<html>
<body>
<div> <!-- THIS DIV -->
<div>
<svg width="100" height="100"><circle cx="6" cy="6" r="5" fill="black"/></svg>
</div>
<div>
<svg width="100" height="100"><circle cx="6" cy="6" r="5" fill="black"/></svg>
</div>
<div>
<svg width="100" height="100"><circle cx="6" cy="6" r="5" fill="black"/></svg>
</div>
</div>
<div>
<div></div>
<div></div>
<div></div>
</div>
<div>
<div>
<svg width="100" height="100"><circle cx="6" cy="6" r="5" fill="black"/></svg>
</div>
<div></div>
<div></div>
</div>
</body>
</html>
I want to select the div which has as sub-node exact 3 svg.
I was thinking like this: /div[ count( .//*[local-name() = 'svg'] ) = 3 ] but not work.

The suggestion by #Slkrasnodar should work, but I doubt selenium supports XPath 2.0 and lower-case() is a 2.0+ function.
Try without it:
//div[count(.//*[local-name() = 'svg']) = 3]
Also, the reason just "svg" doesn't work is because the svg element is in a default namespace. (This is an assumption based on local-name() working; the sample in your question does not have a default namespace.)
You should see if selenium has a way to bind the namespace uri to a prefix and use it in your XPath expressions.

Related

How to manipulate specific div inside a for-loop of EJS?

Been googling around for multiple hours, I want to change the color of the svg of one element during the onClick event, turns out it either style all the elements in the for loop, or just the first one. I added my ejs and toggleSvg() js script here. Hope you can help me.
ejs snippet:
(look for "svg here")
<div class="max-w-5xl mt-14 mx-auto sm:max">
<% posts.forEach(post=> { %>
<div class="my-20">
<div class=" px-2 mb-2 flex items-center justify-between">
<div class="flex items-center">
<div class="border border-gray-300 p-1 rounded-full w-10 h-10 flex items-center bg-white">
<img
src="<%= post.merchant.image %>"
alt="..."
class="w-10"
loading="lazy"
/>
</div>
<p class="pl-5"><%= post.merchant.name %></p>
</div>
<div>
<!--svg here!-->
<svg id="test" xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 cursor-pointer" fill="none" viewBox="0 0 24 24" stroke="currentColor" onclick="toggleSvg()" >
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 5a2 2 0 012-2h10a2 2 0 012 2v16l-7-3.5L5 21V5z"/>
</svg>
</div>
</div>
<!--image carousell-->
<div class="swiper mySwiper">
<div class="swiper-wrapper">
<div class="swiper-slide w-10 h-20 bg-black ">
<div class="justify-center flex ">
<img
src="<%= post.imageUrl[0] %>"
alt="..."
class="h-72"
loading="lazy"
/>
</div>
</div>
<div class="swiper-slide bg-black">
<div class="justify-center flex bg-black">
<img
src="<%= post.imageUrl[1] %>"
alt="..."
class="h-72"
loading="lazy"
/>
</div>
</div>
<div class="swiper-slide bg-black">
<div class="justify-center flex bg-black">
<img
src="<%= post.imageUrl[2] %>"
alt="..."
class="h-72"
loading="lazy"
/>
</div>
</div>
<div class="swiper-slide bg-black">
<div class="justify-center flex bg-black">
<img
src="<%= post.imageUrl[3] %>"
alt="..."
class="h-72"
loading="lazy"
/>
</div>
</div>
</div>
<div class="swiper-button-next"></div>
<div class="swiper-button-prev"></div>
<div class="swiper-pagination"></div>
</div>
<div class="">
<p><span class="font-bold pr-3"><%= post.merchant.name %></span><%= post.description %></p>
</div>
</div>
<% }) %>
</div>`enter code here`
toggleSvg() js:
<script>
function toggleSvg() {
svgElem = document.getElementById("test");
if(svgElem.style.fill === 'red'){
svgElem.style.fill = 'none';
}else{
svgElem.style.fill = 'red';
}
}
</script>
you're using a id in a loop
the can only select one element, if you want to color all svg you can use a class, if you want to color a specific svg you can do it like this
onclick="toggleSvg(this)"
this way you pass the current element when you click
<script>
function toggleSvg(svgElem ) {
if(svgElem.style.fill === 'red'){
svgElem.style.fill = 'none';
}else{
svgElem.style.fill = 'red';
}
}
</script>

Full sizing an image which is into an inline block element

This is my code structure...
<div class="container">
<div class="img-container" style="display:inline-block;">
<img src="image/exaple.png" style="width:100%" />
</div>
</div>
I need to increase the width of the image to 100%. but the img-container div not expanding to 100%. how can i resolve this?

slick carousel in grid mode cutting off bottom of second row

I'm using slick carousel (http://kenwheeler.github.io/slick/).
I have it set for 2 rows with 3 images per row. The trouble is, the second row is getting cut off right through the middle of each image.
Is this some known bug? Anything I can do?
html:
<div class="slick_slideshow" id="slideshow_houses">
<div>
<img src="img/slideshow_houses/image1.jpg" class="slideshow_houses_image" />
<div class="slick-credit">credit1</div>
</div>
<div>
<img src="img/slideshow_houses/image2.jpg" class="slideshow_houses_image" />
<div class="slick-credit">credit2</div>
</div>
<div>
<img src="img/slideshow_houses/image3.jpg" class="slideshow_houses_image" />
<div class="slick-credit">credit3</div>
</div>
<div>
<img src="img/slideshow_houses/image4.jpg" class="slideshow_houses_image" />
<div class="slick-credit">credit4</div>
</div>
<div>
<img src="img/slideshow_houses/image5.jpg" class="slideshow_houses_image" />
<div class="slick-credit">credit 5 </div>
</div>
<div>
<img src="img/slideshow_houses/image6.jpg" class="slideshow_houses_image" />
<div class="slick-credit">credit 6</div>
</div>
</div>
<!-- end slideshow -->
<div style="clear:both;"></div>
jquery:
$('#slideshow_houses').slick({
rows: 2,
slidesPerRow: 3
});
The code you have looks fine. Going by the comments, you had a div that contained the slideshow that had overflow:hidden. In general, any time you have cut-off content you should check any parent div for overflow:hidden.

Convert a html div into image

Below is the code that I want to convert to div.
I tried html2canvas but that did not worked somehow.
The div's uppelayer middlerlayer and bottomlayer are one above other making 3 layers.
<div id="container">
<div id="bottomLayer">
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSivV5yARSKfCsfaFmdo1Iwc7muglbp92befBPfS7XxglZ0XrpU" id="preview2" />
</div>
<div id="mediumLayer">
<img src="http://f0.pepst.com/c/B7F2F3/402463/ssc3/home/038/amazing.beauties/diana_penty_02_12x92.jpg_480_480_0_64000_0_1_0.jpg" id="preview" />
</div>
<div id="main">
<img src="http://f0.pepst.com/c/B7F2F3/402463/ssc3/home/038/amazing.beauties/diana_penty_02_12x92.jpg_480_480_0_64000_0_1_0.jpg" id="jcrop_target" />
</div>
<div id="upperlayer"><canvas id="canvas2"></canvas></div>
</div>

Hide/Show multipe divs jquery

The following FIDDLE shows my current markup.
HTML
<div class="popup-inner-content main-content">
<div class="inner-section one">
<!-- images -->
<div class="media pull-left">
<img src="#" />
</div>
<!-- text -->
<div class="media-aside pull-right">
<h4>Head</h4>
<p>Body</p>
</div>
</div>
<div class="inner-section three is-hidden">
<!-- images -->
<div class="media pull-left">
<img src="#" />
</div>
<!-- text -->
<div class="media-aside pull-right is-hidden">
<h4>Head</h4>
<p>Body</p>
</div>
</div>
<div class="inner-section two is-hidden">
<!-- images -->
<div class="media pull-left ">
<img src="#" />
</div>
<!-- text -->
<div class="media-aside pull-right">
<h4>Head</h4>
<p>Body</p>
</div>
</div>
<div class="thumbnail pull-left">
<!-- thumbnail -->
<div class="media-thumb one">
<img src="#" alt="media-thumbnail" title="media-thumbnail" />
<p>Anchot text</p>
</div>
</div>
<div class="thumbnail pull-left">
<!-- thumbnail -->
<div class="media-thumb two pull-left">
<img src="#" alt="media-thumbnail" title="media-thumbnail" />
<p>Anchor text</p>
</div>
</div>
<div class="thumbnail is-hidden">
<!-- thumbnail -->
<div class="media-thumb three ">
<img src="#" width="128" height="69" alt="media-thumbnail" title="media-thumbnail" />
<p>Anchor Text</p>
</div>
</div>
</div>
</div>
What I am trying to do is always have two thumbnails divs and only one of the inner-section divs visible at a time and essentially be able to toggle through the inner-section and thumbnail divs when clicking any of the anchors inside the thumbnail div.
How could I achieve this using jquery?
Use this:
http://jsfiddle.net/nHXEs/6/
function displayItem(showItem) {
$('div.thumbnail').show();
$('div.thumbnail .' + showItem).parent().hide();
$('div.inner-section').hide();
$('div.inner-section').filter('.' + showItem).show();
}
$(document).ready(function() {
displayItem('one');
$('div.thumbnail').click(function () {
var showItem = '';
if ($('.media-thumb', $(this)).hasClass('one')) {
showItem = 'one';
} else if ($('.media-thumb', $(this)).hasClass('two')) {
showItem = 'two';
} else {
showItem = 'three';
}
displayItem(showItem);
});
});
Hoply it is what you are looking for.
But i hope so.
It is not the best solution, because you use classes to identify your items, but if you allltimes have exactly 3 thumps and big elements it works.
A better solution will be to uses id`s to identify elements
<div class="thumbnail" id="thump_three">
You haven't explained the logic of how to decide which two thumbnails you want to show but here is a good starting point of what I believe you mean by toggle through which should allow you to expand on it. This would show just one of each element.
The idea is that the JS doesn't need to know about 'one', 'two', 'three' etc and just work for an infinite amount of options.
<p>Anchor text</p>
Give the anchor a reference you can use because finding the classes then working out which will be 'one, 'two', 'three', etc will be a lot more work.
You can do this in a few lines but I've made it obvious what's going on.
$('.thumbnail a').on('click', function(e){
e.preventDefault();
// find the wrapper (.thumbnail) and hide it
var $wrapper=$(this).closest('.thumbnail');
$wrapper.hide();
// find the next one
var $next=$wrapper.next();
// if this was the last one get the first instead
if (!$next.length) $next=$wrapper.siblings().filter(':first');
// show it
$next.show();
// now deal with the element that's elsewhere
var ref=this.href.replace('#','');
$('.inner-section.' + ref).show().siblings().hide();
});
Once you've set this behavior up, to save yourself writing out code again (or needing to define functions) just trigger a click on an anchor in the last element so it makes the first one show.
$('.thumbnail:last a').trigger('click');

Resources