This gets pretty specific but I'd like to be able to fade in an arbitrary number of children sequentially and with delayed timing using jquery queue (though I'm open to other methods). Here is what I have working already.
This is the basic html block I'm working with
<header>
<p class="copy">Thing one</p>
<p class="copy">Thing two</p>
<p class="copy">Cat in the Hat</p>
</header>
This current jquery works, but it feels hacky to me in that I need to know in advance how many nodes to expect.
var $screenHeader = $('header');
$screenHeader.queue(function () {
$screenHeader.find('.copy:nth-child(1)').addClass('visible');
$(this).dequeue();
})
.delay(1500)
.queue(function () {
$screenHeader.find('.copy:nth-child(2)').addClass('visible');
$(this).dequeue();
})
.delay(1500)
.queue(function () {
$screenHeader.find('.copy:nth-child(3)').addClass('visible');
$(this).dequeue();
})
.delay(1500);
I would love it if something like this worked
for (var i = 1; i < $screenHeader.children().length+1; i++) {
$screenHeader.queue(function () {
$screenHeader.find('.copy:nth-child('+i+')').addClass('visible');
$screenHeader.dequeue();
}).delay(1500);
}
or better yet
$screenHeader.children().each(function (i) {
$screenHeader.queue(function () {
$screenHeader.find('.copy:nth-child('+i+')').addClass('visible');
$screenHeader.dequeue();
}).delay(1500);
});
or even more betterer (then i'm done, I promise)
$screenHeader.children().each(function () {
$screenHeader.queue(function () {
$(this).addClass('visible');
$screenHeader.dequeue();
}).delay(1500);
});
Now, I know there's some funkiness with how $(this) is passed around so that last one isn't a priority, but it would be really nice to get some sort of loop working. Listing them out and repeating all that code and being tied to the html kills me.
Help would be greatly appreciated. :)
Why not do like this:
var $elements = $('header').find('.copy');
$($elements).each(function(i, ui){
setTimeout(function(){
$(ui).addClass('visible');
},(i*1500));
});
You might consider using CSS for the timing of the animation, instead of jQuery.
See this live example.
And here is the code:
HTML:
<header>
<p class="copy">Thing one</p>
<p class="copy">Thing two</p>
<p class="copy">Cat in the Hat</p>
</header>
CSS:
#keyframes fade-in {
0% { opacity: 0; }
100% { opacity: 1; }
}
header p {
opacity: 0;
animation-name: fade-in;
animation-duration: 1s;
animation-fill-mode: forwards;
}
JS:
$(function() {
$('header').children().each(function(idx) {
$(this).css('animation-delay', idx * 500 + 'ms')
});
});
In my solution, I am using jQuery only for the "arbitrary number of children" part of your question. If you knew the number of children in advance (or, at least had an idea as to what the maximum number of children might ever be), you could do the animation entirely in CSS:
header p:nth-child(2) { animation-delay: 500ms; }
header p:nth-child(3) { animation-delay: 1s; }
/* So on and so forth until your bases are covered... */
(That type of solution would be very easy to generate in a loop using a CSS preprocessor like Sass or Less.)
Figured it out!
$(this) inside the $screenHeader.queue(... loop was the header. I needed to store the child before entering the loop queue part.
var delayTime = 1500,
$screenHeader = $('#screen-'+screenIndex+' header'),
$copyChildren = $screenHeader.children('.copy');
$copyChildren.each(function () {
var child = $(this);
$screenHeader.queue(function () {
child.addClass('visible');
$screenHeader.dequeue();
}).delay(delayTime);
});
Feelin classy.
Related
<html>
<body>
//Id for each item
<p id=1></p>
<p id=2></p>
<p id=3></p>
<script>
for(i = 0; i < 3; i++) {
window.setTimeout(press, 1000);
//Should use For loop variable to fetch and print specific element's Id
function press() {
document.getElementById(i).innerHTML = i;
}
}
</script>
</body>
</html>
I'm a bit of a noob to all of this. Most of these commands I got from w3schools and I'm just trying to piece everything together bit by bit.
You can pass an argument through to the timeout function, so we can use that to display the first value, then increment it and start the timeout again if the value is <= 3:
window.setTimeout(press, 1000, 1);
//Should use For loop variable to fetch and print specific element's Id
function press(j) {
document.getElementById(j).innerHTML = j;
if (++j <= 3) window.setTimeout(press, 1000, j);
}
//Id for each item
<p id=1></p>
<p id=2></p>
<p id=3></p>
An alternative to JavaScript would be to use CSS for this. As a bonus, your page will still work even if JavaScript is disabled.
First, let's start with some clean, valid markup:
<html>
<body>
<div class="popIn">
<p>Paragraph 1</p>
<p>Paragraph 2</p>
<p>Paragraph 3</p>
</div>
</body>
</html>
Now, your CSS (such as in a <style> tag in <head>), add a keyframe animation that sets the visibility to visible right at the last second:
#keyframes popIn {
99% {
visibility: hidden;
}
100% {
visibility: visible;
}
}
Now, add a rule to select all direct descendants of .popIn. In this selector, > means direct decendant of, and * means anything. The rule will set up our animation.
.popIn > * {
animation: 1s popIn;
animation-fill-mode: forwards;
visibility: hidden;
}
If you run this code now, you'll see that after 1 second, everything appears all at once. All we have to do is select the individual paragraphs in-order and change the animation duration.
.popIn *:nth-child(2) {
animation-duration: 2s;
}
.popIn *:nth-child(3) {
animation-duration: 3s;
}
Now, the paragraphs will display one after the other, and no scripting was necessary!
In your case the setTimeout fires only once as it isn't waiting with the loop and i being declared in the scope, hence after the loop it is equal to 3.
You could use setInterval as follows to pass the argument and do a clearInterval when i exceeds number paras:
let i = 1;
const a = window.setInterval(press, 1000, i);
//Should use For loop variable to fetch and print specific element's Id
function press() {
document.getElementById(i).innerHTML = i++;
if (i > 3)
window.clearInterval(a);
}
//Id for each item
<p id="1"></p>
<p id="2"></p>
<p id="3"></p>
Or alternatively you could make the loops like this :
<html>
<body>
//Id for each item
<p id=1></p>
<p id=2></p>
<p id=3></p>
<script>
function press(i) {
if (i < 3) {
setTimeout(function () {
i++;
document.getElementById(i).innerHTML = i;
press(i);
}, 1000);
}
}
press(0);
</script>
</body>
</html>
This code sample works, it does not work with animations of the same duration instead of just an alert.
<script>
var timeoutOne = null,
timeoutTwo = null,
timeoutThree = null;
function alertOne() {
alert('first message');
timeoutOne = setTimeout(alertTwo, 3000);
}
function alertTwo() {
alert('second message');
timeoutTwo = setTimeout(alertThree, 1000);
}
function alertThree() {
alert('third message');
timeoutThree = setTimeout(alertFour, 1000);
}
function alertFour() {
alert('fourth message');
}
function startCountdown() {
alertOne();
}
function stopCountdown() {
clearTimeout(timeoutOne);
clearTimeout(timeoutTwo);
clearTimeout(timeoutThree);
}
</script>
I intended to have multiple links but I'm limited to two. The first link is the working demo of the project. The second is all of the code discussed in the question
working-demo
different-code
I'm working on this project that involves animation and re-calculation of elements/repositioning in the event of a rescale and I can't seem to get it to work. I've been working on this for over a month now, and I've tried at least 20 different iterations.
Note: the links are highlighted code (except for the actual demo of the interactive display).
The timeout-testing link is a short demonstration of four, sequential-alerts being stopped by a single button. This is the effect I'm trying to accomplish with regard to the animation. note that this is just code, not an actual alert/button interface
The shortened-script is the specific problematic-code taken out of the problematic script.
My solution so far is to use three scripts, the calculated/positioned/animated elements are removed, re-added, the three main functions of setup,position,dimensions are recalled as if it was a new page... but I have three scripts so it breaks after the fourth re-scale while the animation is running. I've tried to switch back and forward between two scripts but it doesn't work going from script 2 to 1.
The alert example and shortened-script is my new attempt which tries not to use the three scripts method done in the working demo.
I haven't tried promises/deferred yet. I'm wondering if I'm missing something obvious.
The three scripts used in the working demo are first,second,third-script respectively.
They are pretty much copies of each other with minor differences.
The animationend event is more reliable for what I think you're trying to do. What's nice is that you don't have to try and time the exact moment an animation finishes; you instead rely on the browser. Have a look at this example.
var step_one = document.querySelector('.step.one');
var step_two = document.querySelector('.step.two');
function stepOneHandler() {
step_two.classList.add('go');
}
step_one.classList.add('go');
step_one.addEventListener('animationend', stepOneHandler);
#keyframes move-one-right {
to { transform: translateX(3em); }
}
#keyframes move-two-right {
to { transform: translateX(6em); }
}
.step {
background: red;
display: block;
width: 3em;
height: 1.5em;
margin-bottom: 1em;
}
.step.one.go {
animation: 1s move-one-right forwards;
}
.step.two.go {
animation: 1s move-two-right forwards;
}
<div class="step one"></div>
<div class="step two"></div>
I have an hidden div, and I want to show the hidden div only when user's mouse over another a trigger element for several seconds instead show the hidden div once the user hover the trigger element
here is my javascript code
$('.c_like_icon').mouseover(
function() {
var timeout = setTimeout(function(){
var comment_id=$(this).attr('data-commentId');
$.ajax({
url: 'ajax_c_like_user.php',
method:'post',
data:{comment_id:comment_id},
success:function(data){
var like_num=$('#'+comment_id+'c_like_number').text();
if(like_num>=1){
$('#'+comment_id+'like_user_w').html(data);
$('#'+comment_id+'like_user_w').show();
}
else{
$('#'+comment_id+'like_user_w').hide();
}
}
})
}, 2000); //2 seconds
},
function(){
var comment_id=$(this).attr('data-commentId');
clearTimeout(timeout); //cancel the timeout if they hover off
$('#'+comment_id+'like_user_w').hide();
// do stuff when hover off
}
)
define a timeout in your hover in function and clear in the hover out function, to prevent it being fired if they leave before the time runs out, like this:
var timeout;
$('#trigger').hover(
function() {
timeout = setTimeout(function(){
// do stuff on hover
$('#hiddenDiv').show();
}, 2000); //2 seconds
},
function(){
clearTimeout(timeout); //cancel the timeout if they hover off
// do stuff when hover off
$('#hiddenDiv').hide();
}
);
You can very easily do this CSS only. No jquery is required which presents a huge benefit as it is a big library to download.
Just use delayed transitions. Here is my example (live demo here: http://codepen.io/anon/pen/jbGhi):
HTML
<div id="first"></div>
<div id="second"></div>
In this example, the ids are not necessary but I find it better to understand what happens.
CSS
for the purpose of this example, I'll stylize the divs (to make the hover effect more obvious) but none of the following really matters:
div{
height: 50vmin;
width: 50vmin;
border: solid 5px black;
float: left;
margin-right: 10vmin;
}
and this is where the magic happens:
div#first:hover ~ div#second{
transition: all 0.2s ease 1s;
background-color: green;
}
We are using the css selector "~" that means "any sibling element after (and their children)". In that example it means "a div called #second that is sibling and after a div called #first that is hovered". Basically, as long as the second div is a sibling and after or contained within a sibling (that is after) of the first one, you'll get the desired effect.
And there you go. You can add more delay (change "1s" to whatever duration) before the change occurs, and you can smoothen the transition itself (change "0.2s" to whatever duration).
PS: in the CSS, don't forget to add all vendor prefixes for transition and transform. Always check caniuse.com to know which prefixes are needed. Example:
-webkit-transition: all 1s;
transition: all 1s;
i know its an old question, but i think it should have a vanilla solution
// Element will be the triggerer
let timeOut;
element.addEventListener('mouseover', (e) => {
timeOut = setTimeout(() => {
// Do your stuff here
}, 400);
});
element.addEventListener('mouseout', (e) => {
clearTimeout(timeOut);
});
I made this script, which opens a div with the right class and close the others.
function showhide(id) {
if (document.getElementById) {
var divid = document.getElementById(id);
var divs = document.getElementsByClassName("hideable");
for (var i = 0; i < divs.length; i = i + 1) {
divs[i].style.display = "none";
}
divid.style.display = "block";
}
return false;
}
Is it possible to make some animation, like fadout, easeout instead of just showing it by display options?
You could try this
function showhide(id) {
if (document.getElementById) {
var divid = document.getElementById(id);
var divs = document.getElementsByClassName("hideable");
for (var i = 0; i < divs.length; i = i + 1) {
$(divs[i]).fadeOut("slow");
}
$(divid).fadeIn("slow");
}
return false;
}
Have a look at this fiddle "http://jsfiddle.net/9jtd3/"
There are many more techniques provided by Jquery library, You should have a look at that too.
You can use slideDown() and slidUp() of jQuery
$( document.body ).click(function () {
if ( $( "div:first" ).is( ":hidden" ) ) {
$( "div" ).slideDown( "slow" );
} else {
$( "div" ).slideUp("slow");
}
});
This example will toggle multiple elements with the same class name. This example does not need jquery.
HTML:
<button onclick="fadeInAndOut(this)" style="width:100%">Toggle 1</button>
<div class="accordianPanel acordianPanelHidden accordianPanelStyle">Panel 1</div>
<button onclick="fadeInAndOut(this)" style="width:100%">Toggle 2</button>
<div class="accordianPanel acordianPanelHidden accordianPanelStyle">Panel 2</div>
Javascript:
function fadeInAndOut(thz) {
var elmt = thz.nextElementSibling;//Get the element that is below the button that
//was just clicked
elmt.classList.toggle("acordianPanelHidden");//Toggle the class which changes
//attributes which triggers the `transition` CSS
}
CSS
.accordianPanel {
opacity: 1;
height:100%;
transition: all 1s;
}
.accordianPanel.acordianPanelHidden {
opacity: 0;
height: 0px;
visibility:hidden;/* This must be used or some strange things happen -
What happens is that even though the content of the panel is not shown
any buttons in the content can still be clicked -
So basically there are invisible buttons that can accidently get clicked -
if the visibility is not set to hidden - And the visibility doesn't need to be explicitly changed to visible
from hidden in order to show the content
because if visibility:hidden is not used then by default the content is
displayed -
*/
}
.acordianPanelShown {
height: 100%;
width: 100%;
opacity: 1;
}
.accordianPanelStyle {
background:red;
}
This will surely solve your problem.
You can use .fadeOut() directly if you have included jQuery library in your script.
This is way easier with only CSS.
You make a class
div {
display:block;
transition: all .2s ease-out;
}
.hidden {
display:none;
}
And with javascript, you apply or remove the class hidden when you want to. jQuery animation lib is wayyyy far from good to be used. It's clunky, and ressource eating for your user. CSS works with your GPU instead, allowing a more fluid animation.
If You are using Jquery then another way to do this is
function showhide(id) {
$(".hideable").fadeOut("slow");
$("#" + id).fadeIn("slow");
}
Assuming "hideable" as className in your group of divs
Good luck.
You can do that using a Library like jQuery or something.
You can sure make it using plain javascript, but there's no point doing that since jQuery is an amazing library.
See some examples of show and hide
Is this possible? I've tried visibility:hidden/visibility:visible and display:none/display:block on the classes to switch between, but both result in the element popping in at the end.
When styling the two classes, use the opacity property. .swithClass will be able to transition smoothly between varying opacities.
Example:
.FadeFrom {
opacity: 0.0;
}
.FadeTo {
opacity: 1.0;
}
Look here on how to implement JQuery Fading
http://api.jquery.com/category/effects/fading/
You can handle other events in the fade in and out using the call back function like this:
$('.someClass').fadeIn('slow', function() {
// run extra code here
});
$('.someClass').fadeOut('slow', function() {
// run extra code here
});
Use .animate()
$("#myElement").animate({ opacity: 1, left: 0 }, 1000);
To get .switchClass() to work, you'll have to edit the jQuery code. Find function getElementStyles(). In the else, after if (typeof style[key] === 'string') { add this code:
if (key == "filter" && /^alpha\(opacity=(\d+)\)$/.test(style[key])) {
newStyle.opacity = parseFloat(RegExp.$1) / 100;
}
That should do it.