Selecting nested DOM element - javascript

I am trying to select a nested HTML element with jQuery.
<div id="myTabContent" class="tab-content">
<div role="tabpanel" class="tab-pane fade in active" id="home">
<div class="events_box">
<div class="event_left">
<div class="event_left-item">
<div class="icon_2">
<i class="fa fa-clock-o" id="programHoursId0"></i>
</div>
<div class="icon_2">
<i class="fa fa-location-arrow" id="programLocationId0"></i>
</div>
I have to select the classes fa fa-clock-o and fa fa-location-arrow. I am able to select them by ID but I want select them by class.
I already have tried combinations like:
$('div div div .fa fa-clock-o').css('visibility', 'hidden');
And:
$('.event_left .event_left-item .icon_2 .fa fa-clock-o').css('visibility', 'hidden');
And:
$('div.fa fa-clock-o').css('visibility', 'hidden');
Along with many more....
The goal is to hide those FontAwesome icons.

Since fa and fa-clock-o are classes on the same element you must not have space between them in the selector or jQuery (or any alternative like querySelector) will think one is a descendant of the other. Try this:
$('.fa.fa-clock-o')
// ^^^
div.fa fa-clock-o: look for any descendant of type fa-clock-o (tag) of a div that has the class fa => nothing selected because there is no tag fa-clock-o.
div.fa .fa-clock-o: look for any elements with the class fa-clock-o that are descendants of a div with the class fa => will match what you want.
.fa.fa-clock-o: look for elements that have the classes fa and fa-clock-o => matches what you want too

Please try this $('.fa').hide();

Related

I want to replace the text inside span of parent div

I want to change the text inside span. But span doesn't have a class and parent div doesn't have an id. I can't change the html it is not in my hand. So how can I change text of span with js?
<div class="mobilMenuAcButton">
<span>MENU</span>
<i class="fal fa-bars"></i>
</div>
Something like this
let div = document.querySelector(".mobilMenuAcButton");
let span = div.querySelector("span");
span.innerHTML = "NEW MENU";
<div class="mobilMenuAcButton">
<span>MENU</span>
<i class="fal fa-bars"></i>
</div>
Try using this for setting the text:
node.textContent = yourText
and this to return the value:
node.textContent
MDN Referance
let span = document.querySelector(".mobilMenuAcButton span");
span.textContent = "test";
<div class="mobilMenuAcButton">
<span>MENU</span>
<i class="fal fa-bars"></i>
</div>
Here is an example by using jQuery.
//This can update the content of sample span
$(".mobilMenuAcButton span").html('New Menu');
//If you have multiple span in different level
//better use '>' or first() to specific select the target
//'>' standard for first level of children inside parent
//Both line below can do the works
$(".mobilMenuAcButton > span").html('New Menu');
$(".mobilMenuAcButton span").first().html('New Menu');
<!-- Insert the following line to head tag to use jQuery -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="mobilMenuAcButton">
<span>MENU</span>
<i class="fal fa-bars"></i>
</div>
If you want to change multiple elements you can use querySelectorAll. Afterwards just loop over each element and change its content.
const menuSpans = document.querySelectorAll('.mobilMenuAcButton span, .mobilMenuBT span');
for(const span of menuSpans) {
span.textContent = 'MENÜ';
}
<div class="mobilMenuAcButton">
<span>MENU</span>
<i class="fal fa-bars"></i>
</div>
<div class="mobilMenuBT">
<span>MENU</span>
<i class="fal fa-bars"></i>
</div>

Button works only after second click

Close button which remove the elements from DOM, work only on the second click.
Here is HTML part of button: That is closeBtn.
function removeHeader() {
var list = document.getElementById("main");
list.removeChild(list.childNodes[0]);
}
<div id="main">
<div class="nanoSaturnBanner">
<p>teteasdasdasdsadasds sad asdasdasdasdasdas</p>
<div class="banner-buttons">
<label class="showme">Ads by Google</label>
<a class="infoLink" href="https://support.google.com/adsense/#topic=3373519" target="_blank">
<i class="fas fa-info-circle"></i>
</a>
<div class="closeBtn" onclick="removeHeader()">
closeBtn
</div>
</div>
</div>
</div>
You should use list.childNodes[1] because the list.childNodes[0] represent the #text node that is the whitespaces after <div id="main">. So, in first click it was removing that node and in second click it was removing the actual node with <div class="nanoSaturnBanner">
function removeHeader() {
var list = document.getElementById("main");
list.removeChild(list.childNodes[1]);
}
<div id="main">
<div class="nanoSaturnBanner">
<p>teteasdasdasdsadasds sad asdasdasdasdasdas</p>
<div class="banner-buttons">
<label class="showme">Ads by Google</label>
<a class="infoLink" href="https://support.google.com/adsense/#topic=3373519" target="_blank">
<i class="fas fa-info-circle"></i>
</a>
<div class="closeBtn" onclick="removeHeader()">
<i class="far fa-window-close">close</i>
</div>
</div>
</div>
Note: Whitespace inside elements is considered as text, and text is considered as nodes. Comments are also considered as nodes.
As childNodes get none element nodes as well, like text and comment, use e.g. children instead to get the first actual element.
Note, with that you also make sure getting the element no matter how many "none element nodes" their might be in your markup.
Stack snippet
function removeHeader() {
var list = document.getElementById("main");
list.removeChild(list.children[0]);
}
<div id="main">
<div class="nanoSaturnBanner">
<p>teteasdasdasdsadasds sad asdasdasdasdasdas</p>
<div class="banner-buttons">
<label class="showme">Ads by Google</label>
<a class="infoLink" href="https://support.google.com/adsense/#topic=3373519" target="_blank">
<i class="fas fa-info-circle"></i>
</a>
<div class="closeBtn" onclick="removeHeader()">
<i class="far fa-window-close">close</i>
</div>
</div>
</div>
function removeHeader() {
var list = document.getElementById("main");
list.remove(list.childNodes[0]); // replacing removeChild with remove worked
}
Check the fiddle.

onClick event not working , because of nested tags

onClick event not working , I have this html code
<a class='list-group-item media' href='#'>
<div class='media-body'>
<div class='pull-left'>
<div class='lg-item-heading'></div>
<small class='lg-item-text'></small>
</div>
<div class='pull-right'>
<div class='lg-item-heading'>
<button onClick='alert("Is it working??")' class='btn bg-danger pv20 text-white fw600'>
<i class='fa fa-times' aria-hidden='true'></i>
</button>
</div>
</div>
</div>
</a>
The button element has -> onClick='alert("Is it working??")' , however not working
I guess it's because of the nested elements , it fires on the outer element <a> not on the inner element <button> , how to handle this issue ??
as soon as I hover with my mouse on the inner element <button> - the browser tells me that I'm hovering on <a> tag and in clicking will redirect me to a specific URL
You need to stopPropagation() from your button. That'll prevent it from bubbling up to your <a> element.
function onAnchorClick(e) {
console.log('Anchor clicked');
}
function onButtonClick(e) {
e.stopPropagation();
alert('Is it working');
}
document.querySelector('a').addEventListener('click', onAnchorClick);
document.querySelector('button').addEventListener('click', onButtonClick);
<a class='list-group-item media' href='#'>
<div class='media-body'>
<div class='pull-left'>
<div class='lg-item-heading'></div>
<small class='lg-item-text'></small>
</div>
<div class='pull-right'>
<div class='lg-item-heading'>
<button class='btn bg-danger pv20 text-white fw600'>
<i class='fa fa-times' aria-hidden='true'>Something</i>
</button>
</div>
</div>
</div>
</a>
I also rearranged the code and set the event with an addEventListener instead, as you can't really get the event object you need in order to call stopPropagation().
That said, having a button inside of an anchor isn't a good idea. If you want a link that looks like a button, you should just style the anchor to look like a button. Otherwise, there is no reason to wrap it in an anchor (especially in this example), so you should just remove the anchor.

Move dom elements in loop

We have a page that lists the items in a user's cart. Links are presented with each item for the actions Edit and Remove. We'd like to test the placement of the Edit link by placing it above the remove link using javascript, however I'm not sure how to do it when there are an unknown number of items that could exist within the user's cart.
A snippet from the dom is below:
<div class="item-table first">
<div class="item" data-part-number="ABC123">
<h3 class="item-name">Item 1 name</h3>
<dl>
<dt class="item-attribute">Color:</dt><dd class="item-attribute-value">Blue</dd>
<dt class="edit">Edit</dt><dd></dd>
</dl>
</div>
<div class="item-qty">
<span class="item-qty">QTY:</span>1
<p><a class="delete-item" data-action="delete" href="/deleteitem1url"">Remove Item</a></p>
</div>
</div>
<div class="item-table">
<div class="item" data-part-number="DEF456">
<h3 class="item-name">Item 2 name</h3>
<dl>
<dt class="item-attribute">Color:</dt><dd class="item-attribute-value">Black</dd>
<dt class="edit">Edit</dt><dd></dd>
</dl>
</div>
<div class="item-qty">
<span class="item-qty">QTY:</span>1
<p><a class="delete-item" data-action="delete" href="/deleteitem2url"">Remove Item</a></p>
</div>
</div>
The desired state moves each Edit link to within a new p element above the existing p element that contains Remove Item link.
This should do it:
$('.item-table').each(function() {
var deleteItem = $(this).find('.delete-item');
var editItem = $('<p></p>').append($(this).find('.edit'));
$(deleteItem).before($(editItem));
});
This should do the trick, if you can use jQuery:
$('.item-table .item').each(function() {
$(this).find('.edit').insertBefore($(this).next('.item-qty').find('.delete-item'));
});
Basically, you need to loop through each .item in .item-table. Once you have the .item, you need to find the .edit element and use insertBefore to find the respective .delete-item node and insert the selected .edit node before it.
Here's a working example with jQuery and the actual results.

Toggling Multiple DIVs with JQuery: Codes Included

I need help toggling multiple divs with the codes below. It works well with one div but I will multiple divs would be looped with php so it will be impossible to target each loop to give unique IDs or classes.
Below are the codes, please help out with the correct JQuery
function clickHandler() {
$('#hide').toggle();
$('#show').toggle();
$('.more-content').toggle('slow');
}
$(document).ready(function(){
$('#hide, .more-content').hide();
$('#hide, #show').on('click', clickHandler);
});
HTML
<div class="more-content">
<!--These are the contents-->
</div>
<button id="hide" class="more_arrow">Collapse <span class="fa fa-chevron-up"></span></button>
<button id="show" class="more_arrow">Expand <span class="fa fa-chevron-down"></span></button>
When working with repeating components you don't want to use ID's you want to use common classes for common elements. Then you use an outer container for each repeating "module".
Then you can isolate components within each "module" by only searching within that module instance
HTML - can repeat as many <article> as you want, the script will work for all instances independently
<article>
<div class="content"></div>
<div class="more-content"></div>
<button class="hide" class="more_arrow">Collapse</button>
<button class="show" class="more_arrow">Expand</button>
</article>
JS
$('.hide, .more-content').hide();// should be done with css not js
$('.hide, .show').on('click', clickHandler);
function clickHandler() {
$(this).toggle()
.siblings('.hide, .show')
.toggle()
// only toggle more-content within this instance of <article>
.parent().find('.more-content')
.toggle('slow');
}
You can target the currently clicked div using $(this) within the handler, so
function clickHandler() {
$(this).toggle();
}
Will toggle the currently clicked div.
You can toggle a nearby div to the one clicked using this
$(this).nearest('.someclass').toggle();
Use classes where you have repeating elements you want to access.
Hmmm... looks like i took too much time trying to write a response. Anyway here's another just not to let it go to waste.
js:
function clickHandler() {
console.log($(this).data('link'))
var link = $(this).data('link');
$('.hide[data-link=' + link + ']').toggle();
$('.show[data-link=' + link + ']').toggle();
$('.more-content[data-link=' + link + ']').toggle('slow');
}
$(document).ready(function(){
$('.hide, .more-content').hide();
$('.hide, .show').on('click', clickHandler);
});
HTML:
<div class="more-content" data-link="0">
<!--These are the contents-->
</div>
<button class="hide" class="more_arrow" data-link="0">Collapse <span class="fa fa-chevron-up"></span></button>
<button class="show" class="more_arrow" data-link="0">Expand <span class="fa fa-chevron-down"></span></button>
<div class="more-content" data-link="1">
<!--These are the contents-->
</div>
<button class="hide" class="more_arrow" data-link="1">Collapse <span class="fa fa-chevron-up"></span></button>
<button class="show" class="more_arrow" data-link="1">Expand <span class="fa fa-chevron-down"></span></button>
<div class="more-content" data-link="2">
<!--These are the contents-->
</div>
<button class="hide" class="more_arrow" data-link="2">Collapse <span class="fa fa-chevron-up"></span></button>
<button class="show" class="more_arrow" data-link="2">Expand <span class="fa fa-chevron-down"></span></button>
Essentially, you'll need a variable to specify which button should link to which div. Then you need to put that variable in an attribute of some sort. I chose a data attribute named 'link' but you could also use a class name.
You must give to your divs the same class, in example 'my-class' and hide or show them depend on button clicked.
$(document).ready(function(){
$('#hide').on('click', function(){
// Hide all elements which have my-class class
$('.my-class').hide();
});
$('#show').on('click', function(){
// Show all elements which have my-class class
$('.my-class').show();
});
});
You can too get elements by attribute value. In example by id value
$('[id=test]')
If you give to your elements ids prefix, you should be able to get all of them by this expression
$('[id^=test]')
By changing ^ mark to $ you can search elements with specified postfix
Try this:
jsFiddle Demo
First, surround each content DIV + buttons in a container DIV.
Then, use jQuery traversal methods siblings() and prevAll() to toggle the appropriate DIVs.
HTML:
<div class="container">
<div class="more-content">
Once upon a midnight dreary, while I pondered, weak and weary, Over many a quaint and curious volume of forgotten lore — While I nodded, nearly napping, suddenly there came a tapping, As of some one gently rapping, rapping at my chamber door. "'Tis some visiter," I muttered, "tapping at my chamber door — Only this and nothing more."
</div>
<button class="hide more_arrow">Collapse <span class="fa fa-chevron-up"></span></button>
<button class="show more_arrow">Expand <span class="fa fa-chevron-down"></span></button>
</div>
<div class="container">
<div class="more-content">
The quick brown fox jumped. The quick brown fox jumped. The quick brown fox jumped. The quick brown fox jumped. The quick brown fox jumped. The quick brown fox jumped.
</div>
<button class="hide more_arrow">Collapse <span class="fa fa-chevron-up"></span></button>
<button class="show more_arrow">Expand <span class="fa fa-chevron-down"></span></button>
</div>
<div class="container">
<div class="more-content">
Whatsoever things are true, whatsoever things are honest, whatsoever things are just, whatsoever things are pure, whatsoever things are lovely, whatsoever things are of good report; if there be any virtue, and if there be any praise, think on these things.
</div>
<button class="hide more_arrow">Collapse <span class="fa fa-chevron-up"></span></button>
<button class="show more_arrow">Expand <span class="fa fa-chevron-down"></span></button>
</div>
jQuery:
$(document).ready(function(){
$('#hide, .more-content').hide();
$('#hide, #show').on('click', function(){
$(this).prevAll('.more-content').toggle('slow');
$(this).siblings('button').toggle();
$(this).toggle();
});
});

Categories