Child Visibility Affects Parent Visibility - javascript

I'm having a weird issue when setting a child container to visibility: visible via JavaScript in the $(document).ready function.
Here's the problem:
I'm having a parent element, that has bootstraps helperclass class="d-none".
I now want to set the CSS of the child of this element to visibility: visible.
The problem is that, as long as the $(document).ready function is running, the parent and its child are visible.
This means that some weird stuff is going on, since wrapping a visible element in a hidden element should always show nothing.
But apparently it does show both the parent and the child.
Does anybody know how to fix this?
TO BE SPECIFIC HERE:
I want to call the $(document).ready function
I don't want to see the child, nor the parent when calling the function, as this following code does also not show the child nor the parent because the parent has "d-none"
.parent{
width: 100px;
height: 100px;
}
.child{
width: 50px;
height: 50px;
visibility: visible;
}
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<div class="parent d-none">
<div calss="child">
</div>
</div>
Why can the parent be seen in the below snippet, when setting the visibility of the child via js?
The parent should still have "d-none", and therefore all its children should also not be visible, or what am I understanding wrong here?
To reproduce this issue, copy the lower code snippet to your answer and hit run a few times, you will see the yellow and red rectangles show up for a short amount of time, before they are actually not visible anymore.
$(document).ready(function() {
$(".visi").css("visibility", "visible");
});
.d-none {
background-color: red;
width: 100px;
height: 100px;
}
.visi {
background-color: yellow;
width: 50px;
height: 50px;
}
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
</head>
<div class="d-none">
<div class="visi" style="visibility: visible;"></div>
</div>

Let me start out by saying that I probably do not understand 100% of what you are trying explain. This is what I have gathered please inform me of any differences:
Your while loop was an attempt to reveal the divs at a future time.
loops are way too fast to be any use as a timer you need setTimeout()
JavaScript is asynchronous so if you plan to reveal one div and then the next (I'm guessing here because you weren't really specific), you'll get one possibly finishing before another or possibly way later. You can make times synchronous by using async function and await keyword.
asynchronous: A set to start at 2secs and B set to start at 2.5secs they'll both end possibly at the same time.
synchronous: A starts at 2secs and ends B stars 2.5secs later.
You right to assume that a child is is hidden if the parent is hidden except if the parent has visibility:hidden and a child has visibility: visible the parent will remain hidden and the child will be visible.
Bootstrap class .d-none is entirely different. It is display:none; which practically removes the element from all but HTML. With visibility:hidden the element still takes space. An element with display:none doesn't take up space.
function reveal(selector) {
$(selector).css('visibility', 'visible')
}
const selectors = ['.child', '.parent'];
const times = [3000, 5500];
async function sync(selectors, times) {
const showChild = () => {
return new Promise(resolve => {
setTimeout(() => resolve(reveal(selectors[0])), times[0]);
});
}
const showParent = () => {
return new Promise(resolve => {
setTimeout(() => resolve(reveal(selectors[1])), times[1]);
});
}
await showChild();
await showParent();
}
sync(selectors, times);
.parent {
visibility: hidden;
background-color: red;
width: 100px;
height: 100px;
}
.child {
visibility: hidden;
background-color: yellow;
width: 50px;
height: 50px;
}
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" crossorigin="anonymous">
<div class="parent">
<div class="child"></div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>

Check this code. I fixed some parts.
function myFunction(){
if (1 === 1) {
$(".visi").css("visibility", "visible");
var i = 0;
while(i < 100){
console.log(i++);
}
}
}
.visi {
background-color: yellow;
width: 50px;
height: 50px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<div class="d-none">
<div class="visi" style="visibility: hidden;" ></div>
</div>
<button onclick="myFunction()">Click me</button>
you can set the visibility to hidden at the beginning and then set it to visible

Related

How to make showed div stay unhidden on hover?

I have a jquery function that on hover it shows a hidden div to the side and it works fine. What I wanted to add is when I hover to the showed div ie box2 the div disappears therefore I can't interact with box2 how can I make box 2 stay unhidden when I hover on it then on hover out it fades out again. I can do this easily with vanilla javascript but I need the jquery fade effect so how can I accomplish it with jquery. Any help is appreciated. Thanks in advance.
$("#box1").hover(function(){
$("#box2").fadeIn("slow");
},
function(){
$("#box2").fadeOut();
});
.box1 {
position: absolute;
left: 4%;
width: 20%;
height: 10%;
background-color: black;
}
.box2 {
position: absolute;
left: 24%;
width: 20%;
height: 30%;
background-color: grey;
display:none;
}
<script src="https://code.jquery.com/jquery-3.6.0.min.js"
integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
<div class="box1" id="box1"></div>
<div class="box2" id="box2"></div>
Here are 2 ways to handle it. The one that is commented out will keep box 2 visible until you mouse out of box 2.
The other one (uncommented) will set a short timer and test to see if you're still overing over box 2. I think that's the one you're looking for.
let ontarget = false
$("#box1, #box2").hover(function(e) {
$("#box2").fadeIn("slow");
ontarget = e.target.id == 'box2'
},
function(e) {
// keep open unless mouse out of box 2
//if (e.target.id != 'box1') $("#box2").fadeOut();
// after a short delay (100 ms) test to see if we're still over box2, if so do nothing.
// though if we mouse out it will rerun this if statement to close it like you expect
setTimeout(() => {
if (!ontarget || e.target.id == 'box2') $("#box2").fadeOut();
if (e.target.id == 'box2') ontarget = false
}, 100)
});
.box1 {
position: absolute;
left: 4%;
width: 20%;
height: 10%;
background-color: black;
}
.box2 {
position: absolute;
left: 24%;
width: 20%;
height: 30%;
background-color: grey;
display: none;
}
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
<div class="box1" id="box1"></div>
<div class="box2" id="box2"></div>
You have a couple of options here. First, you could wrap both boxes in a <div>, and just modify the jquery code to show the div on hover.
Another option could be to use the css !important attribute (it is bad habit, however) to add another style rule to show it. This would look as follows:
.box2:hover {
display:block;
}
Feel free to comment with any questions! Good Luck!

Inverting button action on click

I'm working with WordPress site where I want to show elements on button click.
I found this script, but it works the opposite how I want - it hides, instead of shows content. How can I invert it?
I want it to be hidden when pages loads and appear when clicked on button
Preview: https://www.w3schools.com/code/tryit.asp?filename=GGXM3P219FCN
$(document).ready(function () {
var togBtn = $('.tog');
var allergerns = $('.allergerns');
togBtn.one('click', hideAllergerns);
function hideAllergerns() {
allergerns.fadeOut();
togBtn.one('click', showAllergerns);
}
function showAllergerns() {
allergerns.fadeIn();
togBtn.one('click', hideAllergerns);
}
});
.allergerns {
width: 100px;
height: 100px;
background-color: #4aa3df
}
.tog {
width: 60px;
height: 40px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.1/jquery.min.js"></script>
<button class="tog">toggle</button>
<div class="allergerns"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Set the initial CSS styles.
Use JavaScript to toggle a specific class that shows your elements:
References should be stored inside a data-* Attribute, not by copy pasting code in case you need multiple toggling buttons or pane elements
Animations should be done using CSS, not jQuery. Preferably use GPU accelerable CSS properties like opacity, transform etc.
Finally, use jQuery's .toggleClass() to trigger a desired style-state
jQuery(function ($) { // DOM ready and $ alias in scope
$("[data-toggle]").on("click", function() {
$(this.dataset.toggle).toggleClass("is-active");
});
});
.pane {
overflow: auto;
background-color: #4aa3df;
width: 100px;
height: 100px;
transition: 0.3s;
max-height: 0;
opacity: 0;
}
.pane.is-active {
max-height: initial;
opacity: 1;
}
<button class="tog" data-toggle="#pane-1">Toggle 1</button>
<div id="pane-1" class="pane">Pane 1</div>
<button class="tog" data-toggle="#pane-2">Toggle 2</button>
<div id="pane-2" class="pane">Pane 2</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>

How to apply a jQuery effect to an element before page is fully loaded?

I want to make custom height of an element using jQuery. height is being changed but an effect (like blink effect) is being shown on page load every time. How to solve this problem?
$(document).ready(function() {
$('.jQuery-Container').height('100px');
});
.jQuery-Container {
background-color: Red;
height: 700px;
width: 200px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="jQuery-Container">
This is text..!!
</div>
On page load height of the div is being changed but after the page is fully loaded. I want to change height before the page is fully loaded.
You can See my jsfiddle here.
You could do like this, where you run a script immediately after the element, and as long as it is plain javascript, it will work.
.JS-Container {
background-color: Red;
height: 700px;
width: 200px;
}
<head>
<script>
function changeThis(sel) {
document.querySelector(sel).style.cssText = 'height: 100px;';
}
</script>
</head>
<body>
<div class="JS-Container">
This is a sample text
</div>
<script>changeThis('.JS-Container');</script> <!-- this will run before page is fully
loaded, so no "blink" will occur -->
</body>
make you div first hidden then after your jquery logic make div visible
CSS
.jQuery-Container {
background-color: Red;
height: 700px;
width: 200px;
display:none;
}
JS
$(document).ready(function(){
$('.jQuery-Container').height('100px').show();
});

Javascript removeClass() issue

Here is the css code :
.big-square {
position:relative;
height:768px;
width:768px;
border:1px solid black;
background-color:#007da9;
text-align:center;
display:table-cell;
-webkit-transition:all 0.3s linear;
}
and here the html:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<link rel="stylesheet" href="css/style.css" type="text/css">
<script>
function showmenu() {
$(document).ready(function() {
$("#big-square").removeClass("big-square");
});
}
</script>
</head>
<body>
<div id="big-square" onclick="showmenu();" class="big-square">1</div>
<div id="big-square" onclick="showmenu();" class="big-square">2</div>
The problem is when I click on anyone of square, just the first dissapear and I want to make it dissapear separately. For example, if I click on the 2nd square, just the second squuare dissapear.
id must be unique in the whole DOM. (and the relevant functions return only the first one)
What you want is
$(document).ready(function() {
$(".big-square").on('click', function() {
$(this).removeClass("big-square");
});
});
.big-square {
position: relative;
height: 768px;
width: 768px;
border: 1px solid black;
background-color: #007da9;
text-align: center;
display: table-cell;
-webkit-transition: all 0.3s linear;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="big-square">1</div>
<div class="big-square">2</div>
It is illegal HTML to have id's not be unique. Use a class instead if you plan to have 2 or more elements of similar 'stuff'. Then, you shouldn't nest the ready statement in a function. Next, you shouldn't use onclick, instead opting to listen to the event click. Additionally, the css .class does not match an id of your html. Finally to target 1 item only, I would use the jQuery object $(this).
So, all that said, I would re-write your code as:
<script>
$(document).ready(function() {
$(".big-square").click(function() {
$(this).removeClass("big-square");
});
});
</script>
</head>
<body>
<div class="big-square" id="square1">1</div>
<div class="big-square" id="square2">2</div>
That's newbie coding. Let's try to fix it:
1 - Different id's for each element (as user Vic pointed out already)
2 - $(document).ready doesn't need to be nested
3 - onclick="showmenu();" is completely unnecesary and including scripts in the html is bad practice in modern web development
I won't post any code because I see you already have answers with code :)

How to get top level object under the mouse function?

Title says it all. I've got child div's with absolute positions inside a relative parent div, and would like to know whether the mouse is over a child or a parent div at a "random" point in time.
Hypothetically, I'd like to call the .mouseover method and perform a .hasclass test on the highest level object to see if it has the child class or not. However, .mouseover is an event handler, thus not something I could just call to get the relevant information.
Example HTML below:
$(document).ready(function() {
$(".child").draggable();
setTimeout(doSomething, 31415);
});
var doSomething = function() {
// Edit content based on what is underneath the mouse
}
.parent {
width: 100%;
height: 1000px;
position: relative;
background: #f0f0f0;
}
.child {
width: 300px;
height: 100px;
position: absolute;
background: #cccccc;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<link rel="stylesheet" href="http://code.jquery.com/ui/1.11.4/themes/ui-lightness/jquery-ui.css">
<script src="http://code.jquery.com/ui/1.11.4/jquery-ui.min.js"></script>
<div class="parent">
<div class="child"></div>
<div class="child"></div>
</div>
Getting an element from a position is what the document.elementFromPoint function was designed to do:
document.elementFromPoint(mousePosition.x, mousePosition.y);
To get the current mouse position, attach a listener to mousemove (as far as I know there is no native method to extract mouse coordinates without a mouse event). Here's an example fiddle showing this: https://jsfiddle.net/xsLwt8Ld/
If I understood correctly, you want to know if at any given time, the mouse is over the child or directly over the parent. You could achieve it by using the :hover pseudoclass
Create a function that checks if there is any .child that has the :hover class:
If there is, that means that the mouse is over a .child (and you have the element) and there's no need to check the parent.
If there isn't, then check if there is any .parent element that also has the class that you created:
If there is: the mouse is over a .parent but not over a .child;
If there is not: the mouse i not over a .parent or a .child.
The code to achieve this is simple:
function checkMouseOver() {
if ($(".child:hover").length) {
// mouse over a .child
} else if ($(".parent:hover").length) {
// mouse over a .parent (but not over .child)
} else {
// mouse not over a .parent or .child;
}
}
A simple working demo:
$(".child").draggable();
// Edit content based on what is underneath the mouse
function checkMouseOver() {
if ($(".child:hover").length) {
alert("You were over " + $(".child:hover").text());
} else if ($(".parent:hover").length) {
alert("You were over " + $(".parent:hover").attr("id"));
} else {
alert("You are not over a .parent or .child");
}
}
.parent {
width: 100%;
height: 1000px;
position: relative;
background: #f0f0f0;
}
.child {
width: 300px;
height: 100px;
position: absolute;
background: #cccccc;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<link rel="stylesheet" href="http://code.jquery.com/ui/1.11.4/themes/ui-lightness/jquery-ui.css">
<script src="http://code.jquery.com/ui/1.11.4/jquery-ui.min.js"></script>
<button onclick="checkMouseOver()">Check where the mouse is</button>
<div class="parent" id="parent1">
<div class="child">Child 1</div>
<div class="child">Child 2</div>
</div>
<div class="parent" id="parent2">
<div class="child">Child 3</div>
<div class="child">Child 4</div>
</div>
(Click on the page and press tab until you get into the button, then mouse over the different elements and press Enter to trigger the funtion)

Categories

Resources