This question already has answers here:
Find the closest ancestor element that has a specific class
(6 answers)
Closed 2 years ago.
I have an HTML like -
<main>
<section>
<div class="parent">
<div class='level_1'>
<div class='level_2'>
<div class='level_3'>
<span class='click_here'></span>
</div><!--level 3-->
</div><!--level 2-->
</div> <!--level 1-->
</div> <!--parent-->
<section>
<section>
<!-- same as given above -->
<section>
<main>
See there is a span element of class click_here. So If user clicks to this span element I want to grab its grand parent element with having class parent by Javascript.
I know the basic solution like accessing e.parentElement.parentElement.parentElement.parentElement but this is not good because the clicked item might be in more deep level than given in example.
Is their any other solution by using Javascript ?
You can use mouseEvent.target.closest('.parent'); to fetch the closest .parent element of the clicked element and this will work for any arbitrary nesting level. Example:
let span = document.querySelector('span');
span.addEventListener('click', function(e) {
console.log(e.target.closest('.parent'));
});
span {
display: block;
width: 100px;
height: 100px;
background: tomato;
}
<main>
<section>
<div class="parent">
<div class='level_1'>
<div class='level_2'>
<div class='level_3'>
<span class='click_here'></span>
</div><!--level 3-->
</div><!--level 2-->
</div> <!--level 1-->
</div> <!--parent-->
<section>
<section>
<!-- same as given above -->
<section>
<main>
You could do e.target.closest('.parent') which lets you select the closest parent with whatever selector you're looking for.
Related
This question already has answers here:
Get index of element as child relative to parent
(6 answers)
Closed 2 years ago.
I need a simple script that would alert me with index number of certain div within a div.
Hovering over first box gives it's index (0) then another gives 1,2,3 etc.
Result I'm looking for is so third and fourth .box div would give their indexes within .box-container so 0 then 1 and not index of them within whole document. How would I approach such task? I know my code is close just not close enough.
$(".box").mouseover(function() {
console.log($(".box").index($(this)));
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="box-container">
<div class="box">0</div>
<div class="box">1</div>
</div>
<div class="box-container">
<div class="box">2</div>
<div class="box">3</div>
</div>
You are searching .box class specific index() function to get index of element. There is issue due to its getting incremental ways index of element.
if you do using $this their index() it works.
Below is example :
$(".box").mouseover(function() {
console.log($(this).index());
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="box-container">
<div class="box">0</div>
<div class="box">1</div>
</div>
<div class="box-container">
<div class="box">2</div>
<div class="box">3</div>
</div>
I am trying to display a gallery of coaches on a webpage by displaying images with a name. I would like to enable a popup window onClick that will display more information for each coach by toggling the CSS class .-enable {} by targeting specific container divs using their associated ID's. I setup the html so a popup window appears with a "close" button by toggling the css class .enable on that specific container.
I thought to use a really simple function with a parameter to select the id, then toggle a class on the id. In my example, everything wrapped within the first tag is visible by default, and the following div is activated by toggling the css class .-enable. My example "Chris" is a coach and by clicking on the default container block, I activate function "coachWindow(coach)" and pass "Chris" as a parameter in the function to select the div with ID "chris" and toggle the CSS class.
function coachWindow ( coach ) {
document.querySelector("#" + coach).classList.toggle("-enable");
}
.-enable {
display:block;
}
<a onclick="coachWindow(chris)"><div>
<div class="enlarge">
<div class="chris-img coach-img-sizing">
<div class="coach-overlay">
<h3 class="coach-name">Chris</h3>
</div>
</div>
</div>
</a>
<div id="chris" class="coach"> <!--(-enable class appears here)-->
<div class="lightwindow"></div>
<div class="coach-box">
<div class="coach-container">
<h3 class="coach-heading">Chris</h3>
<div class="image-container chris-img coach-img-sizing"></div>
<div class="coach-text">
<p>
Text block on this coach.
</p>
</div>
<button onclick="coachWindow(chris)" class="coach-button">Close</button>
</div>
</div>
</div>
I wasn't sure about the querySelector options, but I saw an example with jQuery that looked like $('#' + parameter) capable of targeting parameter ID's
When I run document.querySelector(chris).classList.toggle("-enable"); from the console, the popup box appears, however running the same id through function coachWindow returns undefined and typeError results.
How can I write my function so I can pass through any coach ID and display the popup window for that corresponding coach?
This is much simpler than you think. First, don't focus on ids as this will make for a more complex and brittle solution. If you structure your HTML correctly, it's just a matter of showing or hiding the appropriate div by locating it with the DOM .closest() and .nextElementSibling() methods and then adding and removing a pre-set class with .classList.add and .classList.Remove. With this approach, it doesn't matter what the ids are (you don't even need to use them) and you can add/remove coaches at any time without having to modify the JavaScript. Just keep the correct HTML structure.
Also, don't use <a> elements just as a click event trigger. Only use them when you are navigating, otherwise it's semantically incorrect. Just about any visible element can have a click event set up on it as you'll see below. Along the same lines, you can style anything to look like anything, so even non-link elements can look like links or buttons or whatever.
Speaking of semantics, don't use headings (h1...h6) because of how they make the text look. In fact, never use any HTML element because of the built-in styling that comes with it. Use the right tag to describe your content and use CSS to style the elements later. An h3 should only ever be used to describe content that is at a third sub-level in a hierarchy. That means that they should only ever appear as children of an h2 and that h2 needs to be in an h1.
// Get all the "links" into an array
let links = Array.prototype.slice.call(document.querySelectorAll("h1.coach-name"));
// Loop over the array of links
links.forEach(function(link){
// Set up a click event handler for each link
link.addEventListener("click", function(){
// Locate the outermost div of the clicked element and
// remove the hidden class from the following element
link.closest(".enlarge").nextElementSibling.classList.remove("hidden");
});
});
// Get all the close buttons into an array
let closeButtons = Array.prototype.slice.call(document.querySelectorAll(".coach-button"));
// Loop through all the close buttons
closeButtons.forEach(function(btn){
// Set up a click event handler for each
btn.addEventListener("click", function(){
// Locate the nearest ancestor div that holds the popup
// and add back the hidden class to hide the current popup
btn.closest(".coach").classList.add("hidden");
});
});
.coach {
border:6px double #e0e0e0;
padding:5px; position:absolute;
top:25px; left:25px;
background-color:#55f;
color:#ff0;
padding:10px;
border-radius:3px;
}
.enlarge h1, .coach h1 {
font-size:1em;
margin-top:.5em;
padding:3px;
text-align:center;
}
.enlarge h1 {
border:1px solid #808080;
background-color:#e0e0e0;
display:inline-block;
border-radius:2px;
width:75px;
cursor:pointer;
}
.enlarge h1:hover { box-shadow:0 0 1px #606060; }
/* This will be set on the popups by default
and then removed as needed. */
.hidden { display:none; }
<div class="enlarge">
<div class="chris-img coach-img-sizing">
<div class="coach-overlay">
<h1 class="coach-name">Chris</h1>
</div>
</div>
</div>
<div id="chris" class="coach hidden"> <!-- each popup is hidden by default via CSS -->
<div class="lightwindow"></div>
<div class="coach-box">
<div class="coach-container">
<h1 class="coach-heading">Chris</h1>
<div class="image-container chris-img coach-img-sizing"></div>
<div class="coach-text">
<p>Text block on this coach.</p>
</div>
<button class="coach-button">Close</button>
</div>
</div>
</div>
<!-- ********************************************** -->
<div class="enlarge">
<div class="chris-img coach-img-sizing">
<div class="coach-overlay">
<h1 class="coach-name">Mary</h1>
</div>
</div>
</div>
<div id="chris" class="coach hidden">
<div class="lightwindow"></div>
<div class="coach-box">
<div class="coach-container">
<h1 class="coach-heading">Mary</h1>
<div class="image-container chris-img coach-img-sizing"></div>
<div class="coach-text">
<p>Text block on this coach.</p>
</div>
<button class="coach-button">Close</button>
</div>
</div>
</div>
<!-- ********************************************** -->
<div class="enlarge">
<div class="chris-img coach-img-sizing">
<div class="coach-overlay">
<h1 class="coach-name">Steve</h1>
</div>
</div>
</div>
<div id="chris" class="coach hidden">
<div class="lightwindow"></div>
<div class="coach-box">
<div class="coach-container">
<h1 class="coach-heading">Steve</h1>
<div class="image-container chris-img coach-img-sizing"></div>
<div class="coach-text">
<p>Text block on this coach.</p>
</div>
<button class="coach-button">Close</button>
</div>
</div>
</div>
<!-- ********************************************** -->
<div class="enlarge">
<div class="chris-img coach-img-sizing">
<div class="coach-overlay">
<h1 class="coach-name">Alice</h1>
</div>
</div>
</div>
<div id="chris" class="coach hidden">
<div class="lightwindow"></div>
<div class="coach-box">
<div class="coach-container">
<h1 class="coach-heading">Alice</h1>
<div class="image-container chris-img coach-img-sizing"></div>
<div class="coach-text">
<p>Text block on this coach.</p>
</div>
<button class="coach-button">Close</button>
</div>
</div>
</div>
I think your code is not complete, since i cannot see the css style that makes your div hidden. i assume it is something like this:
.coach {
display:none;
/* more styling... */
}
This happens because of CSS priorities. When the DOM experiences changes and the element is rendered again, it takes both CSS classes and process them. But, since both classes (what you define for coach and -enable) are together and both try to set display to different values, the rule that is at last is processed.
So, in order to fix this, you need to order your CSS rules in the following way:
.coach {
display:none;
}
.-enable {
display:block;
}
That way, if -enable is present, it will be the last style applied after applying .coach.
There are more rules about this, for instance, if you're applying CSS styles based on ID or element name, there are different priority rules. You can read more here
I am using Uikit 2 (https://getuikit.com/v2) - and I need to solve a problem.
I got this markup: https://codepen.io/anon/pen/jZwNeB
Now I need to do the following. This part:
<div class="toc uk-panel uk-panel-box-primary sticky-toc" style="margin: 0px;"> ...</div>
Should be shown on the left side - right under the time datetime part. But - and this is important: I can not change the source itself. I can only add a class to toc uk-panel uk-panel-box-primary sticky-toc and add custom CSS and custom JS.
Any idea how to solve this?
var obj = document.getElementById("node");
var parent = document.getElementById("parent");
parent.appendChild(obj);
Here, node is the "toc uk-panel uk-panel-box-primary sticky-toc" element.
parent is the "uk-width-large-1-4" element
You can obviously use any other DOM method than the one I have used.
So, if you want to select the DOM of the entity using its class name class, you have to use getElementsByClassName("big long class name")[0] to correctly reference that entity
I just wanted to highlight the appendChild method
I believe the best answer is using CSS, but because I don't know about getukit and I don't know how to solve this using CSS only.
Here you can try with jQuery. Tell me if you want do this using pure JS.
<link href='https://cdnjs.cloudflare.com/ajax/libs/uikit/2.27.5/css/uikit.min.css' rel='stylesheet'>
<div class="uk-grid">
<div class="uk-width-large-1-4">
<p class="uk-article-meta tm-article-date uk-margin-small selectionShareable">
<time datetime="2018-02-12T12:00:58+00:00">12.02.18</time>
</p>
</div>
<div class="uk-width-large-3-4">
<h1 class="uk-article-title">Test Content</h1>
<div class="uk-margin">
<div class="uk-sticky-placeholder" style="height: 52px; margin: 0px;">
<div class="toc uk-panel uk-panel-box-primary sticky-toc" style="margin: 0px;">
<ol class="toc-list ">
<li class="toc-list-item">
Testa
<ol class="toc-list is-collapsible">
<li class="toc-list-item">Test 2</li>
</ol>
</li>
</ol>
</div>
</div>
<p class="selectionShareable">Test Content.</p>
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
$(function(){
function recreate(){
let newElem = $('.sticky-toc').clone();
$('.sticky-toc').remove();
$('.tm-article-date').after(newElem);
}
recreate();
})
</script>
This question already has answers here:
Find nested element in query
(5 answers)
Closed 5 years ago.
I am after some assistance in passing the value of my span classes to a data attribute (data-groups) contained in their parent divs all with the same class (.item). Here is my current code.
<div class="item" href="#" data-groups="">
<div class="caption">
<p><span class="value1"></span>Description</p>
</div>
</div>
<div class="item" href="#" data-groups="">
<div class="caption">
<p><span class="another-value"></span>Description</p>
</div>
</div>
<div class="item" href="#" data-groups="">
<div class="caption">
<p><span class="third-value"></span>Description</p>
</div>
</div>
<script type="text/javascript">
$(".item").attr("data-groups", function() {
return $('.caption p span').attr('class');
});
</script>
This works somewhat but it populates all data-groups attributes with "value1". I am wanting them all to receive the data attribute from their respective child span classes. Eg, First item div should have a 'data-groups'attribute of 'value1', second with 'another-value', etc.
I'm a little rusty with jquery but learning as I go. Any assistance is appreciated.
Try this:
$(".item").attr("data-groups", function() {
return $(this).find('.caption p span').attr('class');
});
I have a series of div's that are populated with an image, title & excerpt.
Many of the 'content' div's have a div with a two lined title, but I'd like for the 'excerpt' div to have a different class added if the title is one lined (24 characters or less).
I figured I'd have a jQuery function that runs through each '.content' div then an if statement compares the amount of characters in the '.contentTitle', if true then it would apply a class to the '.excerpt' div within the same parent .content div.
What I have below is not working. I'm wondering if its because both of the divs (.contentTitle / .contentExcerpt .excerpt) I'm using are children of the container div (.content)
$(".content").each(function(){
if($(".contentTitle").text().length < 22) {
$(".contentExcerpt .excerpt").addClass('TEST');
}
});
<div class="content">
<div class="contentImage"></div>
<div class="contentTitle"><?php the_title(); ?></div>
<div class="contentExcerpt">
<div class="excerpt">
<?php echo(get_the_excerpt()); ?>
</div>
</div>
</div>
When you are using the children of the container div (.content), you didn't check the children of the div whereas you check all other div matching $(".contentTitle").text().length < 22 when there is more than one .content parent div and when one of them is having the length >= 22, the condition will fail.
I have modified the code below to check the children of the parent div.
$(".content").each(function(){
var parent = $(this);
if(parent.find(".contentTitle").text().length < 22) {
parent.find(".contentExcerpt .excerpt").addClass('TEST');
}
});
.TEST {
color: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="content">
<div class="contentImage"></div>
<div class="contentTitle">12345678901234567890123</div>
<div class="contentExcerpt">
<div class="excerpt">
Test content
</div>
</div>
</div>
<div class="content">
<div class="contentImage"></div>
<div class="contentTitle">12345678901234567890</div>
<div class="contentExcerpt">
<div class="excerpt">
Test content
</div>
</div>
</div>
Note: If you replace your code above, you can see, this is not changing the color as one of matching div is having the length >= 22.