Trigger a function at a specific transition value - javascript

I want to trigger a function at a specific transitionY Value.
I found this:
document.getElementById("main").addEventListener("webkitTransitionEnd", myFunction);
document.getElementById("main").addEventListener("transitionend", myFunction);
function myFunction() {
alert('huuh');
}
But it's only a trigger after a transition End. When I scroll down on my Page, a div box change the style value by (transform: translateY(-100%)).
I tried:
if (document.getElementsByClassName('scroll-container').style.transform == "translateY(-100%)")
.......
but it doesn't work.

You can use jQuery's $.animate function. Using progress attribute, you will be getting current status of the animation. e.g.
setTimeout(function() {
var transitionPointReached = false;
$('#some-id').animate({
opacity: 0.1
}, {
duration: 1000,
progress: function(animation, progress, remaining){
console.log('progress called', progress, remaining);
if(!transitionPointReached && progress >= 0.7) {
transitionPointReached = true;
// call the required callback once.
}
}
});
}, 1000);
#some-id {
width: 200px;
height: 200px;
background-color: yellow;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="some-id"></div>
Hope it helps.

or is it possible to trigger a function if the page reaches a new section? Like #0 (<a id="button" href="#0"></a> ) and went to #1 ?
greetings
Here u can see what i mean :
http://salon-lifestyle.de.w0192ceb.kasserver.com/#0

or is it possible to trigger a function if the page reaches a new
section? Like #0 ( ) and went to #1 ?
The Intersection Observer API was designed for such usecases, it allows to triggers callback when the viewport reaches/crosses/has reached a set of children.
Regarding your transition question, you can do something like this but I would not recommend using it. You can fetch the exact value of the transition property using element.cssText
const dummyDiv = document.getElementById('dummy')
// Assuming the transition is linear and lasts 2secs,
// mid-transiton happens after 1000ms
dummyDiv.addEventListener('transitionstart', () => {
window.setTimeout(() => {
dummyDiv.innerHTML = 'mid transition'
}, 1000)
})
dummyDiv.addEventListener('transitionend', () => {
dummyDiv.innerHTML = 'end transition'
})
#dummy{
padding: 50px 100px;
font-size: 35px;
background: #000;
color: #FFF;
transition: 2s linear;
}
#dummy:hover{
background:red
}
<div id="dummy">Hover me</div>

Related

How to use getComputedStyle or other method to return left value of absolute positioned object that transitions on click

Question: In the example below, when the target is clicked how do I return the correct, updated value of the left property? For example, if --moved is applied I'd like it to return 120px. If it is not applied I'd like it to return 100px.
Background: getComputedStyle can be used to return the values of css properties that are applied to an HTML element. However, in the case of elements that use absolute positioning it doesn't work as I had expected.
Example: In the simplified example below when the target is clicked the --moved class is either applied or removed from the target. However, for reasons that I don't understand after --moved is applied or removed getComputedStyle returns the value of left that was correct BEFORE the class was either added or removed. For example, when the target is clicked and --moved is added left is changed to 120px. Yet getComputedStyle still returns the original value of 100px.
Bonus Point: If you click the target rapidly the returned value is often fractional and doesn't return either 100px or 120px. This tells me that when using absolute positioned objects getComputedStyle doesn't return the css value, but in fact returns the current pixel coordinates of the target. How do I get the actual CSS values?
const myTarget = document.querySelector('.target');
const classForMoved = '--moved';
myTarget.addEventListener('click', () => {
const doesTargetContainAdjustment = myTarget.classList.contains(classForMoved);
if (doesTargetContainAdjustment === false) myTarget.classList.add(classForMoved);
if (doesTargetContainAdjustment === true) myTarget.classList.remove(classForMoved);
console.log(getComputedStyle(myTarget).left);
});
.target {
position: absolute;
top: 100px;
left: 100px;
width: 100px;
height: 100px;
background-color: red;
transition: all 500ms linear;
}
.--moved {
left: 120px;
}
<div class="target"></div>
You have clearly mentioned that if click on .target immediately it will give current left position.
SO what's happening in your code is when you click it will add class (which will start animation), however, the function is synchronous it won't wait till transition gets complete so, it will calculate current left position immediately and return it.
You have to keep in mind that transion-duration:500ms means .target will take 500ms to complete its transition, that's why if you just call you getComputedStyle(myTarget).left after or at completion of transition-duration, which is 500ms, then you will receive expected left value.
I have just added promise to completeAction() function inside of click event which will wait till transition gets complete.
completeAction().then((value) => {
console.log(value)
})
Above, code will just run and print value.
const myTarget = document.querySelector('.target');
const classForMoved = '--moved';
style = window.getComputedStyle(myTarget)
duration = +style.getPropertyValue('transition-duration').substring(0, 3) * 1000;
myTarget.addEventListener('click', () => {
const doesTargetContainAdjustment = myTarget.classList.contains(classForMoved);
const completeAction = () => {
return new Promise((resolve, rejected) => {
if (doesTargetContainAdjustment === false) {
myTarget.classList.add(classForMoved);
setTimeout(() => {
resolve(getComputedStyle(myTarget).left);
}, duration);
}
if (doesTargetContainAdjustment === true) {
myTarget.classList.remove(classForMoved);
setTimeout(() => {
resolve(getComputedStyle(myTarget).left);
}, duration);
}
})
}
completeAction().then((value) => {
console.log(value)
})
});
.target {
position: absolute;
top: 100px;
left: 100px;
width: 100px;
height: 100px;
background-color: red;
transition: all 500ms linear;
}
.--moved {
left: 120px;
}
<div class="target"></div>

Scrolling link text on hover - endless marquee effect

I'm looking for a performant and also smooth solution for links that scroll their text inside of their inline-block box like a marquee effect.
$(document).ready(function() {
function scroll(ele){
var s = $(ele).text().substr(1)+$(ele).text().substr(0,1);
$(ele).text(s);
}
scrollInterval = null;
function startScrolling(e) {
if (!scrollInterval) {
scrollInterval = setInterval(function(){
scroll(e)
},100);
}
}
function stopScrolling(e) {
clearInterval(scrollInterval);
scrollInterval = null;
}
$(".mali").hover(function(){
startScrolling($(this));
});
$(".mali").mouseout(function(){
stopScrolling($(this));
});
$(".mali").mousedown(function(){
stopScrolling($(this));
});
});
.mali {
display: inline-block;
background: black;
color: white;
padding: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Something something darkside, Something something complete.
My solution so far is something I actually found here on stackoverlow in another thread and tried to work with it.
Two problems though.
1.) As this is basically using an interval to loop through the single letters this effect is not very smooth. The effect is stuttering.
Has anyone an Idea on how to make this more smooth? Maybe in that case don't use this method at all and maybe use a CSS transition to animate the text?
2.) Does anyone have a clever solution on how to return to the initial state once I hover off? I want the effect on hover but when moving the mouse off the link it should animate back to the initial text state.
Thanks,
Matt
2) You can save initial state and then just revert it:
$(document).ready(function() {
function scroll(ele){
var s = $(ele).text().substr(1)+$(ele).text().substr(0,1);
$(ele).text(s);
}
scrollInterval = null;
function startScrolling(e) {
if (!scrollInterval) {
$(e).data("text", $(e).text());
scrollInterval = setInterval(function(){
scroll(e)
},100);
}
}
function stopScrolling(e) {
clearInterval(scrollInterval);
scrollInterval = null;
$(e).text($(e).data("text"));
}
$(".mali").hover(function(){
startScrolling($(this));
});
$(".mali").mouseout(function(){
stopScrolling($(this));
});
$(".mali").mousedown(function(){
stopScrolling($(this));
});
});
.mali {
display: inline-block;
background: black;
color: white;
padding: 10px;
transition: all .2s;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Something something darkside, Something something complete.
1) As a smooth animation, i thought of this as a PoC. Maybe it will help you with further ideas.
$(document).ready(function() {
// Those global data could be stored in element's data.
var indent = 0,
width = 0,
padding = 10;
function scroll(ele){
// Every iteration decrease indent by value
indent -= 1;
// If is indent greater than or equal than real width
// (width with padding) reset indent.
if(-indent >= width+padding)
indent = 0;
// Aplly property
$(ele).css("text-indent", indent);
}
var scrollInterval = null;
function startScrolling(e) {
if (!scrollInterval) {
// Get text and real width
let text = $(e).text();
width = $(e).width()
$(e)
// Set real width & height, so that container stays
.width($(e).width())
.height($(e).height())
// Save text to data for reset
.data("text", text)
// Add 2 spans with text:
// <span>text</span><span>text</span>
// Where second span has defined padding on the left
.html($("<span>").text(text))
.append($("<span>").text(text).css("padding-left", padding+"px"));
resumeScrolling(e);
}
}
function stopScrolling(e) {
pauseScrolling(e);
// Reset
$(e)
// Revert real text and reset indent
.text($(e).data("text"))
.css("text-indent", indent = 0);
}
function pauseScrolling(e) {
clearInterval(scrollInterval);
scrollInterval = null;
}
function resumeScrolling(e) {
if (!scrollInterval) {
// Every 30ms repeat animation. It must be at least 25x per second
// so it runs smoothly. (So 1 - 40).
scrollInterval = setInterval(function(){
scroll(e)
},30);
}
}
$(".mali").hover(function(){
startScrolling($(this));
});
$(".mali").mouseout(function(){
stopScrolling($(this));
});
$(".mali").mousedown(function(){
stopScrolling($(this));
});
$("#start").click(function(){
startScrolling($(".mali"));
});
$("#stop").click(function(){
stopScrolling($(".mali"));
});
$("#pause").click(function(){
pauseScrolling($(".mali"));
});
$("#resume").click(function(){
resumeScrolling($(".mali"));
});
});
.mali {
display: inline-block;
background: black;
color: white;
padding: 10px;
/*
This could help, but you can't reset text-indent without animation.
transition: all .1s;
*/
overflow: hidden;
vertical-align: middle;
}
/* When you hover element, new span elements
can't take pointer events, so your elements
stays hovered. */
.mali span {
pointer-events: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Something something darkside, Something something complete.
<br><br>
<button id="start">Start</button>
<button id="stop">Stop</button>
<button id="pause">Pause</button>
<button id="resume">Resume</button>
Idea behind this is:
make element overflow:hidden; so no text will overflow
set fix dimension
duplicate text inside
change text indent every x miliseconds (x < 40 so it is smooth, must be at least 25fps)
when it overflows, reset it so it can be in infinite loop

How do I direct JavaScript to a function on a satisfied IF statement? Trying to fix an Alert loop after progress bar completion

This is a very basic question, and for some reason I am having a hard time wrapping my brain around it. I am new and learning so bear with me please.
Here is a progress bar: https://codepen.io/cmpackagingllc/pen/ZNExoa
When the bar has loaded completely it adds the class completed as seen on js line 41.
progress.bar.classList.add('completed');
So say once completed I want to add an Alert that say's "completed". I assume this would be an easy task but because of the way the code is written with the loop seen on line 46/47
loop();
}, randomInterval);
I am unable to incorporate the Alert properly without an alert loop even when I used return false to stop the loop afterwards.
So the route I am trying to take now is to add the alert prompt to the success function found on line 21-25
function success() {
progress.width = progress.bar.offsetWidth;
progress.bar.classList.add('completed');
clearInterval(setInt);
alert("Completed!");
}
But now I am stuck trying to format it correctly so when the if is called on line 36
if (progress.width >= progress.bar.offsetWidth) {
When the if is called on line 36 I want to to jump to the success function instead. No matter how I try it the code fails to execute. How would I format this correctly so it jumps to my function instead of looping after completed?
I would greatly appreciate some assistance with this. I am trying to understand if there is a better way to add the alert. Thank you much.
I read your code with special attention because recently I have been working with some loading bars (but not animated ones).
The problem is that you are using setTimeout() and not setInterval(), so calling clearInterval() has no effect at all. And you really don't need setInterval() because you're already making recursive calls (looping by calling the same function from its body).
I've took the liberty of rewriting your code for you to analyse it. Please let me know if you have any doubts.
NOTE: It's easier in this case to use relative units for the width! So you don't have to calculate "allowance".
let progress = {
fill: document.querySelector(".progress-bar .filler"),
bar: document.querySelector(".progress-bar"),
width: 0
};
(function loop() {
setTimeout(function () {
progress.width += Math.floor(Math.random() * 50);
if (progress.width >= 100) {
progress.fill.style.width = '100%';
progress.bar.classList.add('completed');
setTimeout(function () {
alert('COMPLETED!');
}, 500);
} else {
progress.fill.style.width = `${progress.width}%`;
loop();
}
}, Math.round(Math.random() * (1400 - 500)) + 500);
})();
Like a comment said, there are several timers in your code. Also, success was never executed. Here you have a version that works.
If you are learning, try to make your code as simple as possible, use pseudocode to see in wich step there is an error and try debugging from there.
var progress = {
fill: document.querySelector(".progress-bar .filler"),
bar: document.querySelector(".progress-bar"),
width: 0 };
function setSize() {
var allowance = progress.bar.offsetWidth - progress.width;
var increment = Math.floor(Math.random() * 50 + 1);
progress.width += increment > allowance ? allowance : increment;
progress.fill.style.width = String(progress.width + "px");
}
function success() {
progress.width = progress.bar.offsetWidth;
progress.bar.classList.add('completed');
alert("Completed!");
}
(function loop() {
var randomInterval = Math.round(Math.random() * (1400 - 500)) + 500;
var setInt = setTimeout(function () {
setSize();
if (progress.width >= progress.bar.offsetWidth) {
success();
} else {
loop();
}
}, randomInterval);
})();
.progress-bar {
height: 10px;
width: 350px;
border-radius: 5px;
overflow: hidden;
background-color: #D2DCE5;
}
.progress-bar.completed .filler {
background: #0BD175;
}
.progress-bar.completed .filler:before {
opacity: 0;
}
.progress-bar .filler {
display: block;
height: 10px;
width: 0;
background: #00AEEF;
overflow: hidden;
transition: all 0.5s cubic-bezier(0.25, 0.8, 0.25, 1);
}
.progress-bar .filler:before {
content: '';
display: block;
background: repeating-linear-gradient(-45deg, #00AEEF, #00AEEF 10px, #23c3ff 10px, #23c3ff 20px);
height: 10px;
width: 700px;
border-radius: 5px;
animation: fill 10s linear infinite;
}
#keyframes fill {
from {
transform: translatex(-350px);
}
to {
transform: translatex(20px);
}
}
<div class="progress-bar">
<span class="filler"></span>
</div>

Event 'transitionend' is called too early, it delays rendering

What I'm doing and what's wrong
When I click on a button, a slider shows up. (here is an example of what it looks like, do not pay attention to this code)
The slider shows via an animation. When the animation is finished I should include an HTML page I've loaded from the server. I need to apply the HTML in the slider after the animation otherwise the animation stops (the DOM is recalculated).
My algorithm
Start the request to get the HTML to display inside the slider
Start the animation
Wait the data to be ready and the transition to be finished
Why? If I apply the HTML during the animation, it stops the animation while the new HTML is added to the DOM. So I wait for both to end before step 4.
Apply the HTML inside the slider
Here is the shortened code:
// Start loading data & animate transition
var count = 0;
var data = null;
++count;
$.get(url, function (res) {
data = res;
cbSlider();
});
// Animation starts here
++count;
$(document).on('transitionend', '#' + sliderId, function () {
$(document).off('transitionend', '#' + sliderId);
cbSlider()
});
function cbSlider() {
--count;
// This condition is only correct when both GET request and animation are finished
if (count == 0) {
// Attempt to enforce the frame to finish (doesn't work)
window.requestAnimationFrame(() => { return });
$('#' + sliderId + ' .slider-content').html(data);
}
}
The detailed issue
transitionend is called too early. It makes the last animated frame a lot too long (477.2ms) and the last frame is not rendered at transitionend event.
From the Google documentation, I can tell you that the Paint and Composite step of the Pixel Pipeline is called after the Event(transitionend):
Maybe I'm overthinking this.
How should I handle this kind of animations?
How can I wait the animation to be fully finished and rendered?
I'm not sure why transitionend is fired before the last frame has rendered, but in this (very crude) test it seems that a setTimeout does help...
The first example shows how the html calculation and injection happens too early. The second example wraps the long running method in a setTimeout and doesn't seem to trigger any interuption in the animation.
Example 1: reproduction of your problem
var ended = 0;
var cb = function() {
ended += 1;
if (ended == 2) {
$(".animated").html(createLongHTMLString());
}
}
$(".load").click(function() {
$(".animated").addClass("loading");
$(".animated").on("transitionend", cb);
setTimeout(cb, 100);
});
function createLongHTMLString() {
var str = "";
for (var i = 0; i < 100000; i += 1) {
str += "<em>Test </em>";
}
return str;
};
.animated,
.target {
width: 100px;
height: 100px;
position: absolute;
text-align: center;
line-height: 100px;
overflow: hidden;
}
.target,
.animated.loading {
transform: translateX(300%);
}
.animated {
background: green;
z-index: 1;
transition: transform .2s linear;
}
.target {
background: red;
z-index: 0;
}
.wrapper {
height: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
<div class="animated">Loading</div>
<div class="target"></div>
</div>
<button class="load">load</button>
Example 2: in which a setTimeout seems to fix it
With a setTimeout around the html injection code.
var ended = 0;
var cb = function() {
ended += 1;
if (ended == 2) {
setTimeout(function() {
$(".animated").html(createLongHTMLString());
});
}
}
$(".load").click(function() {
$(".animated").addClass("loading");
$(".animated").on("transitionend", cb);
setTimeout(cb, 100);
});
function createLongHTMLString() {
var str = "";
for (var i = 0; i < 100000; i += 1) {
str += "<em>Test </em>";
}
return str;
};
.animated,
.target {
width: 100px;
height: 100px;
position: absolute;
text-align: center;
line-height: 100px;
overflow: hidden;
}
.target,
.animated.loading {
transform: translateX(300%);
}
.animated {
background: green;
z-index: 1;
transition: transform .2s linear;
}
.target {
background: red;
z-index: 0;
}
.wrapper {
height: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
<div class="animated">Loading</div>
<div class="target"></div>
</div>
<button class="load">load</button>
Well, if transitions are not working for you the way you want to, you can go back a few years and use jQuery animations instead?
(function(slider){
$.get(url, function (res) {
slider.animate({
// put whatever animations you need here
left: "5%",
}, 5000, function() {
// Animation complete.
slider.find('.slider-content').html(res);
});
});
}($('#' + sliderId)));
You can also start both actions at the same time, and then add the html to the document only after the animation has finished and the request is complete, but that would require a flag.
(function(slider){
// whether the animation is finished
var finished = false;
// whether the html has been added already
var added = false;
// your html data
var html = null;
function add() {
if (finished && html && !added) {
// make sure function will only add html once
added = true;
slider.find('.slider-content').html(html);
}
}
$.get(url, function (res) {
html = res;
add();
});
slider.animate({
// put whatever animations you need here
left: "5%",
}, 5000, function() {
// Animation complete.
finished = true;
add();
});
}($('#' + sliderId)));

Flashing text on value change [duplicate]

I'm brand new to jQuery and have some experience using Prototype. In Prototype, there is a method to "flash" an element — ie. briefly highlight it in another color and have it fade back to normal so that the user's eye is drawn to it. Is there such a method in jQuery? I see fadeIn, fadeOut, and animate, but I don't see anything like "flash". Perhaps one of these three can be used with appropriate inputs?
My way is .fadein, .fadeout .fadein, .fadeout ......
$("#someElement").fadeOut(100).fadeIn(100).fadeOut(100).fadeIn(100);
function go1() { $("#demo1").fadeOut(100).fadeIn(100).fadeOut(100).fadeIn(100)}
function go2() { $('#demo2').delay(100).fadeOut().fadeIn('slow') }
#demo1,
#demo2 {
text-align: center;
font-family: Helvetica;
background: IndianRed;
height: 50px;
line-height: 50px;
width: 150px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button onclick="go1()">Click Me</button>
<div id='demo1'>My Element</div>
<br>
<button onclick="go2()">Click Me</button> (from comment)
<div id='demo2'>My Element</div>
You can use the jQuery Color plugin.
For example, to draw attention to all the divs on your page, you could use the following code:
$("div").stop().css("background-color", "#FFFF9C")
.animate({ backgroundColor: "#FFFFFF"}, 1500);
Edit - New and improved
The following uses the same technique as above, but it has the added benefits of:
parameterized highlight color and duration
retaining original background color, instead of assuming that it is white
being an extension of jQuery, so you can use it on any object
Extend the jQuery Object:
var notLocked = true;
$.fn.animateHighlight = function(highlightColor, duration) {
var highlightBg = highlightColor || "#FFFF9C";
var animateMs = duration || 1500;
var originalBg = this.css("backgroundColor");
if (notLocked) {
notLocked = false;
this.stop().css("background-color", highlightBg)
.animate({backgroundColor: originalBg}, animateMs);
setTimeout( function() { notLocked = true; }, animateMs);
}
};
Usage example:
$("div").animateHighlight("#dd0000", 1000);
You can use css3 animations to flash an element
.flash {
-moz-animation: flash 1s ease-out;
-moz-animation-iteration-count: 1;
-webkit-animation: flash 1s ease-out;
-webkit-animation-iteration-count: 1;
-ms-animation: flash 1s ease-out;
-ms-animation-iteration-count: 1;
}
#keyframes flash {
0% { background-color: transparent; }
50% { background-color: #fbf8b2; }
100% { background-color: transparent; }
}
#-webkit-keyframes flash {
0% { background-color: transparent; }
50% { background-color: #fbf8b2; }
100% { background-color: transparent; }
}
#-moz-keyframes flash {
0% { background-color: transparent; }
50% { background-color: #fbf8b2; }
100% { background-color: transparent; }
}
#-ms-keyframes flash {
0% { background-color: transparent; }
50% { background-color: #fbf8b2; }
100% { background-color: transparent; }
}
And you jQuery to add the class
jQuery(selector).addClass("flash");
After 5 years... (And no additional plugin needed)
This one "pulses" it to the color you want (e.g. white) by putting a div background color behind it, and then fading the object out and in again.
HTML object (e.g. button):
<div style="background: #fff;">
<input type="submit" class="element" value="Whatever" />
</div>
jQuery (vanilla, no other plugins):
$('.element').fadeTo(100, 0.3, function() { $(this).fadeTo(500, 1.0); });
element - class name
first number in fadeTo() - milliseconds for the transition
second number in fadeTo() - opacity of the object after fade/unfade
You may check this out in the lower right corner of this webpage: https://single.majlovesreg.one/v1/
Edit (willsteel) no duplicated selector by using $(this) and tweaked values to acutally perform a flash (as the OP requested).
You could use the highlight effect in jQuery UI to achieve the same, I guess.
If you're using jQueryUI, there is pulsate function in UI/Effects
$("div").click(function () {
$(this).effect("pulsate", { times:3 }, 2000);
});
http://docs.jquery.com/UI/Effects/Pulsate
$('#district').css({opacity: 0});
$('#district').animate({opacity: 1}, 700 );
Pure jQuery solution.
(no jquery-ui/animate/color needed.)
If all you want is that yellow "flash" effect without loading jquery color:
var flash = function(elements) {
var opacity = 100;
var color = "255, 255, 20" // has to be in this format since we use rgba
var interval = setInterval(function() {
opacity -= 3;
if (opacity <= 0) clearInterval(interval);
$(elements).css({background: "rgba("+color+", "+opacity/100+")"});
}, 30)
};
Above script simply does 1s yellow fadeout, perfect for letting the user know the element was was updated or something similar.
Usage:
flash($('#your-element'))
You could use this plugin (put it in a js file and use it via script-tag)
http://plugins.jquery.com/project/color
And then use something like this:
jQuery.fn.flash = function( color, duration )
{
var current = this.css( 'color' );
this.animate( { color: 'rgb(' + color + ')' }, duration / 2 );
this.animate( { color: current }, duration / 2 );
}
This adds a 'flash' method to all jQuery objects:
$( '#importantElement' ).flash( '255,0,0', 1000 );
You can extend Desheng Li's method further by allowing an iterations count to do multiple flashes like so:
// Extend jquery with flashing for elements
$.fn.flash = function(duration, iterations) {
duration = duration || 1000; // Default to 1 second
iterations = iterations || 1; // Default to 1 iteration
var iterationDuration = Math.floor(duration / iterations);
for (var i = 0; i < iterations; i++) {
this.fadeOut(iterationDuration).fadeIn(iterationDuration);
}
return this;
}
Then you can call the method with a time and number of flashes:
$("#someElementId").flash(1000, 4); // Flash 4 times over a period of 1 second
How about a really simple answer?
$('selector').fadeTo('fast',0).fadeTo('fast',1).fadeTo('fast',0).fadeTo('fast',1)
Blinks twice...that's all folks!
I can't believe this isn't on this question yet. All you gotta do:
("#someElement").show('highlight',{color: '#C8FB5E'},'fast');
This does exactly what you want it to do, is super easy, works for both show() and hide() methods.
This may be a more up-to-date answer, and is shorter, as things have been consolidated somewhat since this post. Requires jquery-ui-effect-highlight.
$("div").click(function () {
$(this).effect("highlight", {}, 3000);
});
http://docs.jquery.com/UI/Effects/Highlight
function pulse() {
$('.blink').fadeIn(300).fadeOut(500);
}
setInterval(pulse, 1000);
I was looking for a solution to this problem but without relying on jQuery UI.
This is what I came up with and it works for me (no plugins, just Javascript and jQuery);
-- Heres the working fiddle -- http://jsfiddle.net/CriddleCraddle/yYcaY/2/
Set the current CSS parameter in your CSS file as normal css, and create a new class that just handles the parameter to change i.e. background-color, and set it to '!important' to override the default behavior. like this...
.button_flash {
background-color: #8DABFF !important;
}//This is the color to change to.
Then just use the function below and pass in the DOM element as a string, an integer for the number of times you would want the flash to occur, the class you want to change to, and an integer for delay.
Note: If you pass in an even number for the 'times' variable, you will end up with the class you started with, and if you pass an odd number you will end up with the toggled class. Both are useful for different things. I use the 'i' to change the delay time, or they would all fire at the same time and the effect would be lost.
function flashIt(element, times, klass, delay){
for (var i=0; i < times; i++){
setTimeout(function(){
$(element).toggleClass(klass);
}, delay + (300 * i));
};
};
//Then run the following code with either another delay to delay the original start, or
// without another delay. I have provided both options below.
//without a start delay just call
flashIt('.info_status button', 10, 'button_flash', 500)
//with a start delay just call
setTimeout(function(){
flashIt('.info_status button', 10, 'button_flash', 500)
}, 4700);
// Just change the 4700 above to your liking for the start delay. In this case,
//I need about five seconds before the flash started.
Would a pulse effect(offline) JQuery plugin be appropriate for what you are looking for ?
You can add a duration for limiting the pulse effect in time.
As mentioned by J-P in the comments, there is now his updated pulse plugin.
See his GitHub repo. And here is a demo.
Found this many moons later but if anyone cares, it seems like this is a nice way to get something to flash permanently:
$( "#someDiv" ).hide();
setInterval(function(){
$( "#someDiv" ).fadeIn(1000).fadeOut(1000);
},0)
The following codes work for me. Define two fade-in and fade-out functions and put them in each other's callback.
var fIn = function() { $(this).fadeIn(300, fOut); };
var fOut = function() { $(this).fadeOut(300, fIn); };
$('#element').fadeOut(300, fIn);
The following controls the times of flashes:
var count = 3;
var fIn = function() { $(this).fadeIn(300, fOut); };
var fOut = function() { if (--count > 0) $(this).fadeOut(300, fIn); };
$('#element').fadeOut(300, fIn);
If including a library is overkill here is a solution that is guaranteed to work.
$('div').click(function() {
$(this).css('background-color','#FFFFCC');
setTimeout(function() { $(this).fadeOut('slow').fadeIn('slow'); } , 1000);
setTimeout(function() { $(this).css('background-color','#FFFFFF'); } , 1000);
});
Setup event trigger
Set the background color of block element
Inside setTimeout use fadeOut and fadeIn to create a little animation effect.
Inside second setTimeout reset default background color
Tested in a few browsers and it works nicely.
Like fadein / fadeout you could use animate css / delay
$(this).stop(true, true).animate({opacity: 0.1}, 100).delay(100).animate({opacity: 1}, 100).animate({opacity: 0.1}, 100).delay(100).animate({opacity: 1}, 100);
Simple and flexible
$("#someElement").fadeTo(3000, 0.3 ).fadeTo(3000, 1).fadeTo(3000, 0.3 ).fadeTo(3000, 1);
3000 is 3 seconds
From opacity 1 it is faded to 0.3, then to 1 and so on.
You can stack more of these.
Only jQuery is needed. :)
There is a workaround for the animate background bug. This gist includes an example of a simple highlight method and its use.
/* BEGIN jquery color */
(function(jQuery){jQuery.each(['backgroundColor','borderBottomColor','borderLeftColor','borderRightColor','borderTopColor','color','outlineColor'],function(i,attr){jQuery.fx.step[attr]=function(fx){if(!fx.colorInit){fx.start=getColor(fx.elem,attr);fx.end=getRGB(fx.end);fx.colorInit=true;}
fx.elem.style[attr]="rgb("+[Math.max(Math.min(parseInt((fx.pos*(fx.end[0]-fx.start[0]))+fx.start[0]),255),0),Math.max(Math.min(parseInt((fx.pos*(fx.end[1]-fx.start[1]))+fx.start[1]),255),0),Math.max(Math.min(parseInt((fx.pos*(fx.end[2]-fx.start[2]))+fx.start[2]),255),0)].join(",")+")";}});function getRGB(color){var result;if(color&&color.constructor==Array&&color.length==3)
return color;if(result=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color))
return[parseInt(result[1]),parseInt(result[2]),parseInt(result[3])];if(result=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color))
return[parseFloat(result[1])*2.55,parseFloat(result[2])*2.55,parseFloat(result[3])*2.55];if(result=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color))
return[parseInt(result[1],16),parseInt(result[2],16),parseInt(result[3],16)];if(result=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color))
return[parseInt(result[1]+result[1],16),parseInt(result[2]+result[2],16),parseInt(result[3]+result[3],16)];if(result=/rgba\(0, 0, 0, 0\)/.exec(color))
return colors['transparent'];return colors[jQuery.trim(color).toLowerCase()];}
function getColor(elem,attr){var color;do{color=jQuery.curCSS(elem,attr);if(color!=''&&color!='transparent'||jQuery.nodeName(elem,"body"))
break;attr="backgroundColor";}while(elem=elem.parentNode);return getRGB(color);};var colors={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0],transparent:[255,255,255]};})(jQuery);
/* END jquery color */
/* BEGIN highlight */
jQuery(function() {
$.fn.highlight = function(options) {
options = (options) ? options : {start_color:"#ff0",end_color:"#fff",delay:1500};
$(this).each(function() {
$(this).stop().css({"background-color":options.start_color}).animate({"background-color":options.end_color},options.delay);
});
}
});
/* END highlight */
/* BEGIN highlight example */
$(".some-elements").highlight();
/* END highlight example */
https://gist.github.com/1068231
Unfortunately the top answer requires JQuery UI. http://api.jquery.com/animate/
Here is a vanilla JQuery solution
http://jsfiddle.net/EfKBg/
JS
var flash = "<div class='flash'></div>";
$(".hello").prepend(flash);
$('.flash').show().fadeOut('slow');
CSS
.flash {
background-color: yellow;
display: none;
position: absolute;
width: 100%;
height: 100%;
}
HTML
<div class="hello">Hello World!</div>
Here's a slightly improved version of colbeerhey's solution. I added a return statement so that, in true jQuery form, we chain events after calling the animation. I've also added the arguments to clear the queue and jump to the end of an animation.
// Adds a highlight effect
$.fn.animateHighlight = function(highlightColor, duration) {
var highlightBg = highlightColor || "#FFFF9C";
var animateMs = duration || 1500;
this.stop(true,true);
var originalBg = this.css("backgroundColor");
return this.css("background-color", highlightBg).animate({backgroundColor: originalBg}, animateMs);
};
This one will pulsate an element's background color until a mouseover event is triggered
$.fn.pulseNotify = function(color, duration) {
var This = $(this);
console.log(This);
var pulseColor = color || "#337";
var pulseTime = duration || 3000;
var origBg = This.css("background-color");
var stop = false;
This.bind('mouseover.flashPulse', function() {
stop = true;
This.stop();
This.unbind('mouseover.flashPulse');
This.css('background-color', origBg);
})
function loop() {
console.log(This);
if( !stop ) {
This.animate({backgroundColor: pulseColor}, pulseTime/3, function(){
This.animate({backgroundColor: origBg}, (pulseTime/3)*2, 'easeInCirc', loop);
});
}
}
loop();
return This;
}
Put this together from all of the above - an easy solution for flashing an element and return to the original bgcolour...
$.fn.flash = function (highlightColor, duration, iterations) {
var highlightBg = highlightColor || "#FFFF9C";
var animateMs = duration || 1500;
var originalBg = this.css('backgroundColor');
var flashString = 'this';
for (var i = 0; i < iterations; i++) {
flashString = flashString + '.animate({ backgroundColor: highlightBg }, animateMs).animate({ backgroundColor: originalBg }, animateMs)';
}
eval(flashString);
}
Use like this:
$('<some element>').flash('#ffffc0', 1000, 3);
Hope this helps!
Here's a solution that uses a mix of jQuery and CSS3 animations.
http://jsfiddle.net/padfv0u9/2/
Essentially you start by changing the color to your "flash" color, and then use a CSS3 animation to let the color fade out. You need to change the transition duration in order for the initial "flash" to be faster than the fade.
$(element).removeClass("transition-duration-medium");
$(element).addClass("transition-duration-instant");
$(element).addClass("ko-flash");
setTimeout(function () {
$(element).removeClass("transition-duration-instant");
$(element).addClass("transition-duration-medium");
$(element).removeClass("ko-flash");
}, 500);
Where the CSS classes are as follows.
.ko-flash {
background-color: yellow;
}
.transition-duration-instant {
-webkit-transition-duration: 0s;
-moz-transition-duration: 0s;
-o-transition-duration: 0s;
transition-duration: 0s;
}
.transition-duration-medium {
-webkit-transition-duration: 1s;
-moz-transition-duration: 1s;
-o-transition-duration: 1s;
transition-duration: 1s;
}
just give elem.fadeOut(10).fadeIn(10);
This is generic enough that you can write whatever code you like to animate. You can even decrease the delay from 300ms to 33ms and fade colors, etc.
// Flash linked to hash.
var hash = location.hash.substr(1);
if (hash) {
hash = $("#" + hash);
var color = hash.css("color"), count = 1;
function hashFade () {
if (++count < 7) setTimeout(hashFade, 300);
hash.css("color", count % 2 ? color : "red");
}
hashFade();
}
you can use jquery Pulsate plugin to force to focus the attention on any html element with control over speed and repeatation and color.
JQuery.pulsate() * with Demos
sample initializer:
$(".pulse4").pulsate({speed:2500})
$(".CommandBox button:visible").pulsate({ color: "#f00", speed: 200, reach: 85, repeat: 15 })

Categories