2

I'm trying to learn to improve my code and not repeat myself. I'm trying to use .css() to make an aesthetic design element "flash" before disappearing. I have the result working but I am sure there is a better/shorter way to write this.

At the moment I am setting four intervals which handle changing the CSS.

setTimeout( function(){
   $(outputID).css('border-right','2px solid #fff');
},500);
setTimeout( function(){
   $(outputID).css('border-right','2px solid #343434');
},1000);
setTimeout( function(){
   $(outputID).css('border-right','2px solid #fff');
},1500);
setTimeout( function(){
   $(outputID).css('border-right','2px solid #343434');
},2000);

What would be the best way to do this, using the DRY principle? Loop through a 500 millisecond interval and then cancel based on 2000 milliseconds? Using .delay() somehow?

Lucky
  • 14,677
  • 16
  • 104
  • 145
Francesca
  • 22,178
  • 26
  • 80
  • 145

5 Answers5

2

You can use a data-driven approach

var objA = [{
    duration: 500,
    style: '2px solid #fff'
}, {
    duration: 1000,
    style: '2px solid #343434'
}, {
    duration: 1500,
    style: '2px solid #fff'
}, {
    duration: 2000,
    style: '2px solid #343434'
}];

for (var i = 0; i < objA.length; i++) {
    (function(i) {
        setTimeout(function() {
            $(outputID).css('border-right', objA[i].style);
        }, objA[i].duration);
    })(i);
}

Make sure to make a closure in the loop by using an IIFE to preserve the i variable

Community
  • 1
  • 1
AmmarCSE
  • 28,122
  • 5
  • 36
  • 49
2

Pure CSS can handle this kind of task via Keyframe Animations. I created a fiddle to get you started, but it needs to be adjusted (especially as I left out vendor prefixes). It basically boils down to this:

@keyframes borderblink {
  0% {
    border: 2px solid blue;
  }
  49% {
    border: 2px solid blue;
  }
  50% {
    border: 2px solid white;
  }
  100% {
    border: 2px solid white;
  }

}

.mybox.border-animated {
     border: 2px solid blue;
     animation-name: borderblink;
     animation-duration: 0.4s;
     animation-iteration-count: 10;
}

If you want to support browsers which do not include this feature (IE8+9, Opera Mini), you could use Modernizr for feature detection and only call your javascript solution if needed. But as it is only a visual goodie, I would probably not go that far if you don't already have Modernizr included.

panepeter
  • 1,924
  • 21
  • 26
  • I attempted this sort of solution myself first. However it does not flash (e.g on or off) it *fades* between the two. Even in your example, although it's very fast it's not going from on to off. It's going between the two with a fading animation. I'm looking for a lightswitch whereas this solution is a dimmer switch. – Francesca Jun 09 '15 at 10:02
  • `@keyframes` is a way to go. Just tweak the sequence. Using JS for that would be a crime. – strah Jun 09 '15 at 10:06
  • @Francesca it's really just a matter of setting the right keyframes. I updated the fiddle and the answer. – panepeter Jun 09 '15 at 14:27
1

To elaborate on my comment for jquery animate:

$(outputID)
    .delay(500)
    .animate({ borderColor: "#fff" }, 10)
    .delay(500)
    .animate({ borderColor: "#343434" }, 10)
    .delay(500)
    .animate({ borderColor: "#fff" }, 10)
    .delay(500)
    .animate({ borderColor: "#343434" }, 10)

You can use variables of course for delay times, the 500 matches the question timeouts and the 10 reduces the animation 'effect' so to flashes rather than pulses.

freedomn-m
  • 21,261
  • 4
  • 28
  • 53
0

There are a lot of ways of achieving this. With "pure" JavaScript with a little bit of jQuery, you would do something like:

// flash an element and call the callback when done
var flash = function(element, cb) {
    var counter = 0;
    var max = 4;
    var state = false;

    var animate = function() {
        // assume we have to css classes "off" and "on"
        if (state)
            element.removeClass("on").addClass("off");
        else
            element.removeClass("off").addClass("on");
        state = !state;

        counter++;
        if (counter<max)
            setTimeout(animate, 500);
        else {
            // make sure we end up in "off" state
            element.removeClass("on").addClass("off");
            if (cb instanceof Function) cb();
        }
    }

    animate();
}

// use it like
flash(myElement, function () {
    // we can even do stuff when flashing has stopped, how cool is that!
});
Octav Zlatior
  • 421
  • 2
  • 13
0

Hello if you consider best way, then according to me you can use css animation keyframes. http://www.w3schools.com/cssref/css3_pr_animation-keyframes.asp

But if you want only to do the job via javascript then you can go with ammarcse' answer.

Dinesh Patra
  • 1,065
  • 11
  • 22