Finding next element of a specific class inside a parent jQuery - javascript

I have the following:
<div class="container">
Test 1
<div class="child">Testing</div>
</div>
<div class="container">
Test 2
<div class="child">Testing</div>
</div>
<div class="container">
Test 3
<div class="child">Testing</div>
</div>
I wish to have the child div inside the container thats hovered over to show and hide when the mouse has left the container.
I do currently have:
$('.container').hover(
function () {
$(this).next('.child').show();
},
function () {
$(this).next('.child').hide();
}
);
However it does not seem to work.
Any advice appreciated, thanks.

next() is for siblings, you should use children for children :)...
$('.container').hover(
function () {
$(this).children('.child').show();
},
function () {
$(this).children('.child').hide();
}
);

use find() instead of next as it is a child element and not a sibling one:
$('.container').hover(
function () {
$(this).find('.child').show();
},
function () {
$(this).find('.child').hide();
}
);

Related

Hide element only if it contains specific text inside, using Java Script

I have these elements on my page:
<div id="123test"><p>test</p></div>
<div id="123test"><p>othertext</p></div>
And I am trying to remove the div if it contains "test" text inside, using Java Script, but it does not seem to work.
Here is my JS:
var container = document.getElementById('123test');
if (container.textContent=='test') {
container.style.display="none";
};
var container = document.getElementById('123test');
if (container.textContent == 'test') {
container.style.display = "none";
};
<div id="123test"><p>test</p></div>
<div id="123test"><p>othertext</p></div>
I also tried using :contains selector way, but the result was the same. The style of the container does not change at all. What do I do wrong? Is there another approach possible? This code is a simplified version of my project, but neither of these two work. I would be very gratefull if someone would help me to overcome the issue.
Make sure your HTML looks exactly like this:
<div id="123test"><p>test</p></div>
<!-- no whitespace or line breaks before or after <p>test</p> -->
and not like this
<div id="123test">
<p>test</p>
</div>
To avoid this problem, call trim() on container.textContent:
var container = document.getElementById('123test');
if (container.textContent.trim() == 'test') {
container.style.display = "none";
};
<div id="123test">
<p>test</p>
</div>
<div id="123test2">
<p>othertext</p>
</div>
And I am trying to remove the div if it contains "test" text inside, using Java Script [...]
If it is sufficient that test is contained, check for includes('test') instead:
var container = document.getElementById('123test');
if (container.textContent.includes('test')) {
container.style.display = "none";
};
<div id="123test">
<p>test123</p>
</div>
<div id="123test2">
<p>othertext</p>
</div>
Important sidenote: You cannot have more than one element with the same id.
Sidenote 2: :contains only exists in jQuery, not in CSS.
Sidenote 3 about using innerText: This had been my first approach, but for some strange reason on Safari/MacOS it won't hide the container:
var container = document.getElementById('123test');
if (container.innerText == 'test') {
container.style.display = "none";
};
console.log(container.innerText.length); // 6 (!) on Safari/MacOS
<div id="123test">
<p>test</p>
</div>
<div id="123test2">
<p>othertext</p>
</div>
Here is an example of checking an arbitrary DOM tree for text nodes that contain the string "test" and then hiding them by setting display: none;.
The function hideTestNodes accepts NodeList and primarily makes use of nodeType and textContent.
const wrapper = document.getElementById('wrapper')
const hideTestNodes = (children) => {
for (const child of children) {
if (child.nodeType === 1) {
// If the node is another Element, check its child nodes
hideTestNodes(child.childNodes)
}
// If the node is a text node and the content includes 'test'
// then hide the parent element containing the text node
if (child.nodeType === 3 && /test/i.test(child.textContent)) {
child.parentElement.style.display = 'none'
}
}
}
hideTestNodes(wrapper.childNodes)
<div id="wrapper">
<div>
<p>test</p>
</div>
<div>
<p>some other text</p>
</div>
<div>
<p>some deeply <span> nested test</span> text</p>
</div>
<div>
<p>this <span>includes</span> test.</p>
</div>
</div>
If you want to do that to only one specific div, then it's very simple:
NOTE: I added two seconds to let you see how it happens. you can remove the timer.
let test1 = document.getElementById("test1");
if (test1.innerHTML.includes("test")) {
setTimeout(() => {
test1.style.display = "none";
}, 2000);
}
<div id="container">
<div id="test1"><p>test</p></div>
<div id="test2"><p>othertext</p></div>
</div>
If you want to check all divs, it's still simple and you just need to make an array from them then use forEach loop to check all divs in that container:
let divs = document.getElementById("container").children;
[...divs].forEach(div => {
if (div.textContent.includes("test")) {
setTimeout(() => {
div.style.display = "none";
}, 2000);
}
});
<div id="container">
<div id="test1"><p>test</p></div>
<div id="test2"><p>othertext</p></div>
</div>

condition to check whether any element has a specific class

I have a javascript loop that contains a conditional statement.
I need the condition to check whether the current item in the loop contains any element with a specific class name.
This is what I currently have, however as you'll see this is not correct.
Currently my condition checks whether the current element has a specific class name, HOWEVER, I need it to check whether ANY element inside the element has a specific class name.
selectionList.forEach(selectionItem => {
if (selectionItem.classList.contains('myclass')) {
// do something
} else {
// do something different
}
}
EDIT:
I'm editing this post because it seems that people are misunderstanding.
I just need help with the following line in my code:
if (selectionItem.classList.contains('myclass')) {
The above checks whether the current element has a specific class name, but I need it to check whether the current element contains any CHILD element with a specific class name.
You can use .querySelector(selector) to search for children of some element.
!!element.querySelector(selector) will return true if it finds something matching selector inside that element, and will return false otherwise.
let elements = document.querySelectorAll('.outer');
elements.forEach(el => {
let hasChildren = !!el.querySelector('.searchClass');
console.log(`${el.classList[1]} has children with .searchClass: ${hasChildren}`);
});
<div class="outer outer-1">
<div class="inner searchClass"></div>
</div>
<div class="outer outer-2">
<div class="inner"></div>
</div>
<div class="outer outer-3">
<div class="inner">
<div class="inner searchClass"></div>
</div>
</div>
You can use Element.querySelector(selector) or either Element.querySelectorAll(selector).length in order to check if there is a child with the given selector:
yourElements.forEach(element => {
if (element.querySelector(yourSelector)) {
// do something
} else {
// do something different
}
})
// if there is no "something different" to do would be like this
yourElements.filter(elem => !!elem.querySelector(yourSelector))
.forEach(element => {
// do something
})
In your case could be something like
selectionList.forEach(selectionItem => {
if (selectionItem.querySelector('.myclass')) {
// do something
} else {
// do something different
}
})
Instead of a loop, just call .querySelectorAll() with the class name passed in (prefixed with a .) on the element you wish to examine to return a collection of all the elements that contain that class. You can check the resulting collection's .length to see how many elements were found and you can loop over the collection (with .forEach()) to enumerate them individually.
// Find every element that has the myclass class and put them in a collection
let matchingElements = document.querySelectorAll(".match");
let count = matchingElements.length; // Count how many there are
// Loop over the collection
matchingElements.forEach(function(element){
// Do whatever you want with the current element being enumerated
console.log(element.textContent);
});
<div class="needsChecking">
<p>something</p>
<p class="match">bingo</p>
stuff
<div>
<div class="match">bingo
<h1 class="match">bingo</h1>
<h2 class="nomatch"></h2>
</div>
</div>
<div class="needsChecking">
<p>something</p>
<p class="match">bingo</p>
stuff
<div>
<div class="match">bingo
<h1 class="match">bingo</h1>
<h2 class="nomatch"></h2>
</div>
</div>
<div class="needsChecking">
<p>something</p>
<p class="match">bingo</p>
stuff
<div>
<div class="match">bingo
<h1 class="match">bingo</h1>
<h2 class="nomatch"></h2>
</div>
</div>
You can use the children property.
See my snippet below, I've included some notes.
//get parent element
var parent = document.querySelector('.parent');
//get children
var children = parent.children;
//run a loop and check if children have a specific class name
for (let i = 0; i < children.length; i++) {
if (children[i].classList.contains('child1')) {
//log the children with class name child1
console.log(children[i])
}
}
<div class="parent">
<p class="child1"></p>
<p class="child1"></p>
<p class="child2"></p>
<p class="child3"></p>
</div>

How to get the event target inside the parent component in ReactJS

I have a Main component with code
changeColor = (color) => {
}
toggle = (e) => {
console.log(e.target)
}
<div>
<EditComponent changeColor={this.changeColor.bind(this)}>
<TextComonent toggle={this.toggle.bind(this)}>
</div>
Edit component is
color = (value) => {
this.props.changeColor(value)
}
<div>
<button value='red' onClick={this.color.bind(this,"red")}>Red</button>
<button value='blue' onClick={this.color.bind(this,"blue")}>Blue</button>
</div>
Text component is
toggle = (e) => {
this.props.toggle(e)
}
<div>
<p class="black-color" onClick={this.toggle.bind(this)}>Text 1</p>
<p class="black-color" onClick={this.toggle.bind(this)}>Text 2</p>
</div>
I will be clicking on Text 1 or Text 2 first and I will get the event inside toggle function. Next I will click the button Red or Blue. Then I want to change the class to either red-color or blue-color for that particular Text that i have clicked before. How can I get the event inside the parent component to find the particular text or is there any other way to to this?
I want to get the event.target inside the Parent component. I got the event object in parent but event.target is null
<div>
<EditComponent changeColor={this.changeColor.bind(this)}>
<TextComonent toggle={this.toggle}>
</div>
try this way dont bind function in parent component and try,you will get the target
You are not using "bind" correctly. You don't need to bind with an anonymous function.
class Hello extends React.Component {
render() {
return (
<div>
<p onClick={(e) => this.toggle(e)}>
Test
</p>
</div>);
}
toggle = (e) => {
console.log(e.target.innerText);
}
}
From the event variable in toggle, you can perform your changes as need be.
I found the exact solution as to add event.persist(); to get the event.target inside parent component.

Execute function when clicking on DOM element in Vue.js

I want to execute a function when I'm clicking on elements in the dom with a specific class. It just doesn't work, but I'm also receiving any error. This is my
code snippet:
methods: {
initTab: function(){
document.querySelectorAll('.element').onclick = this.nextTab()
}
},
mounted: function () {
this.initTab()
}
I
I want to execute the function every time I click on the element. Would be very thankful if anybody could help me :)
There's very little need (if at all) for document.querySelectorAll() in a Vue app.
In this situation you can take advantage of delegation:
<div #click="onClick">
<!-- Clicks on any element inside this div will be handled -->
</div>
methods: {
onClick(e) {
if (e.target.classList.contains('element')) {
// Handle the click
}
}
}
Add #click="initTab($event)" to the document or template root, that allows you to track every click event on your template, that way you could put your logic to the elements which have only .element class name. If you're using it in a component you could do : <template> <div #click="initTab($event)"> ... </div> </template>
var app = new Vue({
el: '#app',
data() {
return {
}
},
methods: {
nextTab(){
console.log("You clicked on an element with class name =element")
},
initTab(event){
let targetClassNames=event.target.className.split(" ");
targetClassNames.filter(e=>{
if(e==="element"){
this.nextTab();
}
});
}
},
mounted() {
}
})
#app{
height:100px;
display:grid
}
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.17/dist/vue.js"></script>
<div id="app" #click="initTab($event)">
<button class="element">1</button>
<button class="element btn">2</button>
<button class="btn">3</button>
<button class="element btn-primary">4</button>
<button class="btn elementory">5</button>
</div>
You're trying to use general javascript logic within vue. This is not often a good idea.
What I do in such cases is something like this:
<component-name #click="nextTab(tabName)"></component-name>
However, in a v-for loop you can also do something like this:
<ul v-for="tab in tabs">
<li #click="nextTab(tab)">{{tab}}</li>
</ul>
That way in methods you only need:
methods: {
nextTab: function(tab){
// whatever it is you want to do here
}
},
And you won't need mounted at all.
Conclusion: try to avoid repetition by creating components or elements (like li) that repeat - not by trying to add an event-listener to a class.

Polymer paper-collapse item change class of parent

I have a Polymer <paper-collapse-item> inside a <div> inside another <div>. When the <paper-collapse-item> is opened, I want to change add another class to the <div class="container">. But Polymer tells me the function is undefined. Right now I have:
HTML:
<div class="container>
<h1>Header</h1>
<div class="box" onclick="[[_expandBox()]]">
<paper-collapse-item class="header" header="">
<p class="longText">Some long text</p>
</paper-collapse-item>
</div>
</div>
Script:
<script>
Polymer({
is: 'text-page',
_expandBox: function() {
var exp = this.getElementsByClassName("header")[0];
var expPar = this.getElementsByClassName("box")[0].parentNode;
if (exp.hasAttribute(opened)) {
expPar.className += " paropen";
}
}
});
</script>
So how I can I call the function properly and make it add a class to the container?
EDIT
I've made some changes to the entire setup for different reasons. Still left with this issue.
HTML:
<div class="container>
<h1>Header</h1>
<collapse-item opened="{{opened}}" on-tap="_expandBox(opened)"></collapse-item>
</div>
Script:
<script>
Polymer({
is: 'text-page',
_expandBox: function(opened) {
var exp = this.getElementsByClassName("container")[0];
if (opened) {
exp.className += " paropen";
}
}
});
</script>
This tells me that: listener method _expandBox(opened) not defined
Thanks for helping me learn. I'm new to Polymer.
Following Polymer Documentation, you have to write "on-" followed by gesture event type. You have to remove brackets within event handler too. In your case:
<div class="box" on-click="_expandBox">
EDIT:
On on-tap event declaration you must to add a listener, in this case on-tap="_expandBox" (without parameters). When the event tap occurs, an event object is passed automatically to the function as the first parameter:
_expandBox: function(event) {
console.log(event.detail);
}
Your code could be:
HTML:
<div class="container>
<h1>Header</h1>
<collapse-item id="collapseItem" on-tap="_expandBox" opened="[[_functionWithParamsThatChangesThis(param1, param2, ...)]]"></collapse-item>
</div>
Script:
<script>
Polymer({
is: 'text-page',
_expandBox: function() {
var exp = this.getElementsByClassName("container")[0];
if (this.$.collapseItem.opened) {
exp.className += " paropen";
}
}
_functionWithParamsThatChangesThis(param1, param2, ...) {
if (param1, param2, ...) return true;
return false;
}
});
</script>

Categories

Resources