Take attribute value from where style display is not none - javascript

I have few divs:
<div clas="modal-body step step-1" data-step="1" style="display: block;"></div>
<div clas="modal-body step step-2" data-step="2" style="display: none;"></div>
<div clas="modal-body step step-3" data-step="3" style="display: none;"></div>
I would like to get the value of attribute "data-step" where style: display is not none.
Is it possible with JavaScript or JQuery?

You can use the :visible selector in jQuery. This will create a node list (like the querySelectorAll that will contain only the item /s that is not hidden. Then you can get the data-step value of that element.
let visibleStep =$(".step:visible");
console.log(visibleStep.attr('data-step')); // gives 1
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="wathever">
<div class="modal-body step step-1" data-step="1" style="display: block;">A</div>
<div class="modal-body step step-2" data-step="2" style="display: none;">B</div>
<div class="modal-body step step-3" data-step="3" style="display: none;">C</div>
</div>

I just did some sketch on fiddle, try it and let me know if is what you need sir. This is a pure javascript solution.
let nodeList = document.getElementById("wathever").querySelectorAll(".step");
nodeList.forEach(function(div){
if(div.style.display!="none"){
//do something
let dataStep = div.dataset.step;
console.log(dataStep);
}
});
<div id="wathever">
<div class="modal-body step step-1" data-step="1" style="display: block;">A</div>
<div class="modal-body step step-2" data-step="2" style="display: none;">B</div>
<div class="modal-body step step-3" data-step="3" style="display: none;">C</div>
</div>

Related

Hide and Show Elements Based on Date Change from DatePicker

The following solution works, but I would like to keep adding elements for the entire month.
When I remove the dates that are ="none" the previous dates start stacking on top of each other.
Is there a way to simplify the javascript so I wouldn't have to keep adding each date to the if-else statements to hide and show them?
function selectDate() {
var x = document.getElementById("start").value;
if (x == "2022-03-21") {
document.getElementById("2022-03-21").style.display = "flex";
document.getElementById("2022-03-22").style.display = "none";
document.getElementById("2022-03-23").style.display = "none";
}
else if (x == "2022-03-22") {
document.getElementById("2022-03-22").style.display = "flex";
document.getElementById("2022-03-21").style.display = "none";
document.getElementById("2022-03-23").style.display = "none";
}
else if (x == "2022-03-23") {
document.getElementById("2022-03-23").style.display = "flex";
document.getElementById("2022-03-21").style.display = "none";
document.getElementById("2022-03-22").style.display = "none";
}
}
<section>
<div class="container ">
<div class="row">
<div class="col">
<input type="date" id="start" onchange="selectDate()">
</div>
</div>
<div class="row" id="2022-03-21" style="display: none;">
<div class="col">
<div class="row">
<div class="col">
<h4>1</h4>
</div>
<div class="col">
<h4>2</h4>
</div>
</div>
</div>
</div>
<div class="row" id="2022-03-22" style="display: none;">
<div class="col">
<div class="row">
<div class="col">
<h4>3</h4>
</div>
<div class="col">
<h4>4</h4>
</div>
</div>
</div>
</div>
<div class="row" id="2022-03-23" style="display: none;">
<div class="col">
<div class="row">
<div class="col">
<h4>5</h4>
</div>
<div class="col">
<h4>6</h4>
</div>
</div>
</div>
</div>
</div>
</section>
I'm not sure what you mean by
When I remove the dates that are ="none" the previous dates start stacking on top of each other.
I don't see that happening in your snippet.
That said, you can simplify the code that hides/shows the div, and not have to hard code in the dates.
Give each element that you are wanting to show/hide a common class name, for example output
Select them all in a NodeList collection using document.querySelectorAll('.output')
Then with the .forEach() on that collection, you can loop through each one and change the display to none.
Then find the element that matches the date selected
If it is not null, then you can change the display to 'flex'
Personally I prefer to use document.querySelector() or document.querySelectorAll() method when selecting elements.
However, you'll notice that in step 4 above, I didn't. Since the ID begins with a number, it is better to use document.getElementById() rather than document.querySelector(). You can still do it, but it requires some string manipulation. See this post here: Using querySelector with IDs that are numbers
document.querySelector(`#start`).addEventListener(`change`, function(e) {
// Get every element with the 'output' class &
// loop through each one & change the display to 'none'
document.querySelectorAll(`.output`).forEach(el => el.style.display = `none`);
// get the element that matches the value of the date selected
const dispElm = document.getElementById(this.value);
// if the element exists, then change the display to 'flex'
if (dispElm) {
dispElm.style.display = `flex`;
}
});
<section>
<div class="container">
<div class="row">
<div class="col">
<input type="date" id="start">
</div>
</div>
<div class="row output" id="2022-03-21" style="display: none;">
<div class="col">
<div class="row">
<div class="col">
<h4>1</h4>
</div>
<div class="col">
<h4>2</h4>
</div>
</div>
</div>
</div>
<div class="row output" id="2022-03-22" style="display: none;">
<div class="col">
<div class="row">
<div class="col">
<h4>3</h4>
</div>
<div class="col">
<h4>4</h4>
</div>
</div>
</div>
</div>
<div class="row output" id="2022-03-23" style="display: none;">
<div class="col">
<div class="row">
<div class="col">
<h4>5</h4>
</div>
<div class="col">
<h4>6</h4>
</div>
</div>
</div>
</div>
</div>
</section>

How to get certain element (using JavaScript) from HTML with similar classes?

How can I get one certain element from HTML using JavaScript.
I have this code.
<div class="Content">
<div class="First Block">
<div class="num">Text From First Block</div>
</div>
<div class="Second Block">
<div class="num">Text From Second Block</div>
</div>
<div class="Third Block">
<div class="num">Text Third Second Block</div>
</div>
</div>
I want to write "Text From Second Block".
If I write this code
console.log(document.querySelector('.num').innerText);
I will get "Text From First Block"
You can do this in a few simple ways.
Use parent selector .Second.Block. Like this:
document.querySelector('.Second.Block > .num').innerText
Also, querySelector() allows you to specify pseudo-classes such as :nth-child(). Like this:
document.querySelector('.Block:nth-child(2) > .num').innerText
And use querySelectorAll(), referring as a collection, indicating the index in square brackets. Like this:
document.querySelectorAll('.num')[1].innerText
console.log(document.querySelector(".Second.Block > .num").innerText);
console.log(document.querySelector(".Block:nth-child(2) > .num").innerText);
console.log(document.querySelectorAll(".num")[1].innerText);
<div class="Content">
<div class="First Block">
<div class="num">Text From First Block</div>
</div>
<div class="Second Block">
<div class="num">Text From Second Block</div>
</div>
<div class="Third Block">
<div class="num">Text Third Second Block</div>
</div>
</div>
instead of using queryselector you can use getElementsByClassName() and instead of enter the index number of your tag
console.log(document.getElementsByClassName("Block")[i].innerHTML)
You could use document.querySelectorAll
console.log(document.querySelectorAll(".num")[1].innerText)
<div class="Content">
<div class="First Block">
<div class="num">Text From First Block</div>
</div>
<div class="Second Block">
<div class="num">Text From Second Block</div>
</div>
<div class="Third Block">
<div class="num">Text Third Second Block</div>
</div>
</div>

Hidding/showing divs with javascript with timer

This site has saved me a milion times, but now i am trying to make something similar to the header section of this site, and can't quite get it to work. I would like someone to help me with the following:
Here is my example code :
<div class="container">
<div class="row" style="padding-top: 50px;">
<div class="col-md-4">
<div id="first" class="cube color1"></div>
<div id="second" class="cube color3" style="display: none;"></div>
</div>
<div class="col-md-4">
<div id="first" class="cube color2"></div>
<div id="second" class="cube color1" style="display: none;"></div>
</div>
<div class="col-md-4">
<div id="first" class="cube color3"></div>
<div id="second" class="cube color2" style="display: none;"></div>
</div>
</div>
<div class="row" style="padding-top: 50px;">
<div class="col-md-4">
<div id="first" class="cube color3"></div>
<div id="second" class="cube color2" style="display: none;"></div>
</div>
<div class="col-md-4">
<div id="first" class="cube color2"></div>
<div id="second" class="cube color1" style="display: none;"></div>
</div>
<div class="col-md-4">
<div id="first" class="cube color1"></div>
<div id="second" class="cube color3" style="display: none;"></div>
</div>
</div>
</div>
The javascript :
<script>
setInterval(hide, 2000);
function switchDivs()
{
var first = document.getElementById("first");
var second = document.getElementById("second");
}
function hide() {
document.getElementById("first").style.display="none";
document.getElementById("second").style.display="block";
}
function show() {
document.getElementById("first").style.display="block";
document.getElementById("second").style.display="none";
}
</script>
link to jsfiddle
I dont understand first why it doesnt change all the "first" divs into "second", it changes only the first div. Than the next question is how to make that action repeat over time, preferably more like random timer for each one of the 6 positions/boxes.
Shortly: I need divs with id="first" to be swapped with divs with id="second" , after like 5-10 seconds delay after loading the page. Than after the same delay, i need them to switch back to showing only divs with id="first" and so on... (something like setInterval function).
setInterval(function() { $(".color-blocks .col-md-4").each(function() { $(this).children().toggle(); }); }, 2000);
a simple line of code could be helpful, and in a simpler way.
working fiddle : https://jsfiddle.net/65k788u6/3/
while you use ids, those should be unique, so instead use toggle() in order to make it look simpler.
sorry, I don't have 50 rep to leave a comment. Is the problem is that you have multiple elements with the same ID? getElementById() seems to be returning the first instance that's true and not further with the same ID. I would recommend using getelementsbyclassname() and using classes instead of ID's to describe groups of elements. Updated the fiddle to show it done this way. version 4.
Your HTML is invalid. The ID attribute on any element should always be unique within the context of the entire page.
Instead of .getElementById, which selects only one item (and only by its ID attribute) you can use .querySelectorAll to get all elements that match a given CSS query selector (or .querySelector to get a single element).
I recommend using setTimeout instead of setInterval as a general best practice.
var rows = document.querySelectorAll(".col-md-4");
var indices = getIndices(rows);
setTimeout(flipRows, 5000);
function getIndices() {
var arr = [];
for (var i = 0, len = rows.length; i < len; i++) {
arr.push(i);
}
return arr;
}
function flipRows() {
if (indices.length == 0) {
indices = getIndices();
}
var index = Math.random() * indices.length >>> 0;
var randomRow = rows[indices[index]];
indices.splice(index, 1);
flipRow(randomRow);
setTimeout(flipRows, 5000); // run again in 5 seconds
}
function flipRow(row) {
var first = row.querySelector(".first");
var second = row.querySelector(".second");
if (first.style.display === "none") {
first.style.display = "block";
second.style.display = "none";
} else {
first.style.display = "none";
second.style.display = "block";
}
}
.color1 { background-color: pink;}
.color2 { background-color: lightblue;}
.color3 { background-color: lightgreen;}
<div class="container">
<div class="row" style="padding-top: 50px;">
<div class="col-md-4">
<div class="first cube color1">first</div>
<div class="second cube color3" style="display: none;">second</div>
</div>
<div class="col-md-4">
<div class="first cube color2">first</div>
<div class="second cube color1" style="display: none;">second</div>
</div>
<div class="col-md-4">
<div class="first cube color3">first</div>
<div class="second cube color2" style="display: none;">second</div>
</div>
</div>
<div class="row" style="padding-top: 50px;">
<div class="col-md-4">
<div class="first cube color3">first</div>
<div class="second cube color2" style="display: none;">second</div>
</div>
<div class="col-md-4">
<div class="first cube color2">first</div>
<div class="second cube color1" style="display: none;">second</div>
</div>
<div class="col-md-4">
<div class="first cube color1">first</div>
<div class="second cube color3" style="display: none;">second</div>
</div>
</div>
</div>

Boostrap modal element offset giving zero

To scroll to an element in my Bootstrap modal, I can check the offset of the element. There are for instance 8 div's, each with their own id (#row-1, #row-2, etc.). If I open the modal and then input the following into the console, I get the correct offset value.
$('#row-6').offset()['top'];
But when I console.log this into the code itself, after opening the modal with .modal('show'), I get 0 back.
How can this difference occur? I tried all the solutions I could find on here, but all solutions gave me the same 0.
My problem would also be solved if I could scroll to the element in any other way with JavaScript.
You must wait for the modal to be shown:
// The modal is shown
$('#yourModal').on('shown.bs.modal', function() {
// Get the right offset
var offset = $("#yourelement").offset();
var offsetTop = offset.top;
var offsetLeft = offset.left;
});
My guess would be that the elements are not done being shown yet in order to give you the correct value? Try using a setTimeout to verify this:
setTimeout(function(){ $('#row-6').offset()['top']; }, 3000);
You said:
My problem would also be solved if I could scroll to the element in
any other way with javascript.
So, here is my suggestion to your problem:
html:
<button id="modal_show" class="btn btn-warning">Show modal</button>
<div id="myModal" class="modal modal-flex fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true" style="margin-top:60px;">
<div class="modal-dialog">
<div class="modal-content" style="padding:5px;">
<div class="modal-body">
<div class="row" id="row1">
<div class="col-xs-12">
<p>
This is row 1
</p>
</div>
</div>
<div class="row" id="row2">
<div class="col-xs-12">
<p>
This is row 2
</p>
</div>
</div>
<div class="row" id="row3">
<div class="col-xs-12">
<p>
This is row 3
</p>
</div>
</div>
<div class="row" id="row4">
<div class="col-xs-12">
<p>
This is row 4
</p>
</div>
</div>
<div class="row" id="row5">
<div class="col-xs-12">
<p>
This is row 5
</p>
</div>
</div>
<div class="row" id="row6">
<div class="col-xs-12">
<p>
This is row 6
</p>
</div>
</div>
<div class="row" id="row7">
<div class="col-xs-6">
<p>
This is row 7
</p>
</div>
<div class="col-xs-6">
<p class="pull-right">
<span class="scroller" data-to="3">Go To 3</span>
</p>
</div>
</div>
<div class="row" id="row8">
<div class="col-xs-6">
<p>
This is row 8
</p>
</div>
<div class="col-xs-6">
<p class="pull-right">
<span class="scroller" data-to="2">Go To 2</span>
</p>
</div>
</div>
</div>
<div class="modal-footer">
<div class="row">
<div class="col-xs-12 pull-right">
<button type="button" class="btn btn-warning" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<!-- /.modal-content -->
</div>
<!-- /.modal-dialog -->
</div>
Jquery:
$('#modal_show').on('click', function(){
$('#myModal').modal({show: true});
});
$('.scroller').click(function(){
var targetId = $(this).attr("data-to");
$('#myModal').animate({
scrollTop: $("#row"+targetId).position().top
}, 1000);
});
and some css:
.row {
min-height:100px;
}
.scroller {
cursor:pointer;
text-decoration:underline;
}
When you scroll down to div's 7 and 8, you will notice links that scroll you up to div #3 and #2 respectively.
working fiddle: http://jsfiddle.net/xL9at8sc/
Hope that helps you and others...

jquery: run script without affecting divs with same classes

Got a product loop, where I need to change images on click. Like in every product loop, there is a whole bunch of divs with same classes. Which in my case get affected. Can't isolated them. Initial image does disappear. But not a single one, that's intended, but all of them. And no new images appear
html of the single product
<div class="product">
<div class="galwrap displaytable">
<div class=" galitem galitem1"></div>
<div class=" galitem galitem2"></div>
</div>
<div class="displaytable galcolors">
<div class="displaytablecell galcolor galcolor1"></div>
<div class="displaytablecell galcolor galcolor2"></div>
</div>
</div>
and jquery
$(".product").each(function () {
$(this).find(".galcolor2").click(function () {
$(".galitem").hide();
$(this).parent().find(".galitem2").show();
});
});
http://jsfiddle.net/h1twaf1y/
http://jsfiddle.net/q72nw00t/2/
Javascript:
$(".galcolor2").click(function(){
$(".galitem").hide();
$(this).parent().parent().find(".galitem2").show();
});
HTML: (this is just a section repeated over and over again)
<div class="product">
<div class="galwrap displaytable">
<div class=" galitem galitem1">this will be hidden</div>
<div class=" galitem galitem2" style="display: none">this will be shown</div>
</div>
<div class="displaytable galcolors">
<div class="displaytablecell galcolor galcolor1"></div>
<div class="displaytablecell galcolor galcolor2">click this</div>
</div>
</div>
----------
<div class="product">
<div class="galwrap displaytable">
<div class=" galitem galitem1">this will be hidden</div>
<div class=" galitem galitem2" style="display: none">this will be shown</div>
</div>
<div class="displaytable galcolors">
<div class="displaytablecell galcolor galcolor1"></div>
<div class="displaytablecell galcolor galcolor2">click this</div>
</div>
</div>
----------
<div class="product">
<div class="galwrap displaytable">
<div class=" galitem galitem1">this will be hidden</div>
<div class=" galitem galitem2" style="display: none">this will be shown</div>
</div>
<div class="displaytable galcolors">
<div class="displaytablecell galcolor galcolor1"></div>
<div class="displaytablecell galcolor galcolor2">click this</div>
</div>
</div>
Basically you want to listen for any clicks on ALL .galcolor2, then when that is clicked, hide all .galitem, and then only show the RELATED .galitem2 by going up two levels to the div.product and finding the correct item
The problem in your initial code, is that you only went up ONE level with parent() to div.galcolors where you should have instead went up TWO levels with parent().parent(), up to div.product.
You want to find .galitem relative to the item clicked, the way you can find that is to use $.closest(). Closest will travel up the DOM tree (starting with the current node) until it finds a matching selector, which is much better than using parent because you're not dependent on the DOM structure making your code less brittle and easier to read. So your code would look like this instead:
$(".product").each(function(){
$(this).find(".galcolor2").click(function(){
$(".galitem").hide();
$(this).closest(".product").find(".galitem2").show();
});
});

Categories

Resources