4
\$\begingroup\$

I'm pretty new to client side scripting and I'm still learning.

I've written this JS plugin which animates blocks of HTML (fade-in from left/top/right/bottom) as you scroll down the page.

Everything seems to be works correctly, but was just wondering if there is anyone who could suggest how I can improve on this?

e.g:

  • Reduce the size of the code.
  • Structure the plugin better.
  • Stop repetitive code.
  • Increase browser compatibility.
  • Make better use of jQuery keywords.

Really, just doing the same thing, but, written better!

CSS:

<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.4/css/bootstrap.css" media="all" rel="stylesheet" type="text/css">
<style type="text/css">
body {
    height: 100%;
    overflow-x: hidden;
}

.animate {
    position: relative;
}

.bg-info {
    padding: 10px;
    text-align: center;
}

HTML:

<div class="container">
<div class="row">
    <div class="col-xs-3">
        <div class="animate bg-info" data-animation="left" data-distance="200" data-speed="1000" data-delay="0" data-offset="80" data-easing="easeInOutBack">Nulla vel varius dolor. In pellentesque mi ac congue pulvinar. Sed cursus tincidunt condimentum. Curabitur vel velit leo. Nulla condimentum dolor dui, nec convallis elit congue eu.</div>
    </div>
    <div class="col-xs-3">
        <div class="animate bg-info" data-animation="top" data-distance="200" data-speed="1000" data-delay="500" data-offset="80" data-easing="easeInOutBack">Nulla vel varius dolor. In pellentesque mi ac congue pulvinar. Sed cursus tincidunt condimentum. Curabitur vel velit leo. Nulla condimentum dolor dui, nec convallis elit congue eu.</div>
    </div>
    <div class="col-xs-3">
        <div class="animate bg-info" data-animation="bottom" data-distance="200" data-speed="1000" data-delay="1000" data-offset="80" data-easing="easeInOutBack">Nulla vel varius dolor. In pellentesque mi ac congue pulvinar. Sed cursus tincidunt condimentum. Curabitur vel velit leo. Nulla condimentum dolor dui, nec convallis elit congue eu.</div>
    </div>
    <div class="col-xs-3">
        <div class="animate bg-info" data-animation="right" data-distance="200" data-speed="1000" data-delay="1500" data-offset="80" data-easing="easeInOutBack">Nulla vel varius dolor. In pellentesque mi ac congue pulvinar. Sed cursus tincidunt condimentum. Curabitur vel velit leo. Nulla condimentum dolor dui, nec convallis elit congue eu.</div>
    </div>        
</div>

JavaScript:

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.3/jquery.js"></script>
<script type="text/javascript" src="https://code.jquery.com/ui/1.11.4/jquery-ui.js" ></script>
<script type="text/javascript">
    (function ($) {
        $.fn.animateSliders = function(options) {
            var style = { opacity: "0", "-ms-opacity": "0" };
            var settings = $.extend({
                offset: 80,
                distance : 200,
                animation: "left",
                easing: "easeInOutBack",
                speed: 1000,
                delay: 0
            }, options);

            $(".animate").each(function () {
                loadvalues($(this));
                if (settings.animation == 'left') {
                    $(this).css({ left: -settings.distance + 'px' }).css(style);
                }
                if (settings.animation == 'top') {
                    $(this).css({ top: -settings.distance + 'px' }).css(style);
                }
                if (settings.animation == 'right') {
                    $(this).css({ right: -settings.distance + 'px' }).css(style);
                }
                if (settings.animation == 'bottom') {
                    $(this).css({ bottom: -settings.distance + 'px' }).css(style);
                }
            });

            $(window).on("scroll load", function() {
                $(".animate").each(function () {
                    loadvalues($(this)); 
                    var i = parseFloat(settings.offset) / 100;
                    var trigger = $(window).height() * i + $(window).scrollTop();
                    var position = $(this).offset().top;

                    if (settings.animation == 'bottom') {
                        position = position - settings.distance;
                    }
                    if (settings.animation == 'top') {
                        position = position + settings.distance;
                    }

                    if (position < trigger) {
                        if (settings.animation == 'left') {
                            $(this).delay(settings.delay).animate({ 'left': '0px', opacity: 1 }, settings.speed, settings.easing);
                        }
                        if (settings.animation == 'top') {
                            $(this).delay(settings.delay).animate({ 'top': '0px', opacity: 1 }, settings.speed, settings.easing);
                        }
                        if (settings.animation == 'right') {
                            $(this).delay(settings.delay).animate({ 'right': '0px', opacity: 1 }, settings.speed, settings.easing);
                        }
                        if (settings.animation == 'bottom') {
                            $(this).delay(settings.delay).animate({ 'bottom': '0px', opacity: 1 }, settings.speed, settings.easing);
                        }
                    };
                });
            });

            function loadvalues(obj) {
                if (obj.attr('data-animation')) {
                    settings.animation = obj.data("animation");
                };

                if (obj.attr('data-offset')) {
                    settings.offset = obj.data("offset");
                };

                if (obj.attr('data-distance')) {
                    settings.distance = obj.data("distance");
                };

                if (obj.attr('data-easing')) {
                    settings.easing = obj.data("easing");
                };

                if (obj.attr('data-speed')) {
                    settings.speed = obj.data("speed");
                };

                if (obj.attr('data-delay')) {
                    settings.delay = obj.data("delay");
                };
            }
        };
    }(jQuery));

    $(document).ready(function () {
        $.fn.animateSliders({offset : 200});
    });
</script>
\$\endgroup\$
3
\$\begingroup\$

Just a few quick notes, this code block:

if (settings.animation == 'left') {
    $(this).delay(settings.delay).animate({ 'left': '0px', opacity: 1 }, settings.speed, settings.easing);
}
if (settings.animation == 'top') {
    $(this).delay(settings.delay).animate({ 'top': '0px', opacity: 1 }, settings.speed, settings.easing);
}
if (settings.animation == 'right') {
    $(this).delay(settings.delay).animate({ 'right': '0px', opacity: 1 }, settings.speed, settings.easing);
}
if (settings.animation == 'bottom') {
    $(this).delay(settings.delay).animate({ 'bottom': '0px', opacity: 1 }, settings.speed, settings.easing);
}

Is performing the same action no matter what the value is, so you could reduce it to either:

if (settings.animation) {
    var animationOptions = {
       opacity: 1
    };
    animationOptions[settings.animation] = '0px';
    $(this).delay(settings.delay).animate(animationOptions, settings.speed, settings.easing);
}

or checking that the value is one of 'left', 'right', 'top', 'bottom'

if (~['left', 'right', 'top', 'bottom'].indexOf(settings.animation)) {
    var animationOptions = {
       opacity: 1
    };
    animationOptions[settings.animation] = '0px';
    $(this).delay(settings.delay).animate(animationOptions, settings.speed, settings.easing);
}

You could apply the same reduction to this code block:

$(".animate").each(function () {
    loadvalues($(this));
    if (settings.animation == 'left') {
        $(this).css({ left: -settings.distance + 'px' }).css(style);
    }
    if (settings.animation == 'top') {
        $(this).css({ top: -settings.distance + 'px' }).css(style);
    }
    if (settings.animation == 'right') {
        $(this).css({ right: -settings.distance + 'px' }).css(style);
    }
    if (settings.animation == 'bottom') {
        $(this).css({ bottom: -settings.distance + 'px' }).css(style);
    }
});

Additionally, your loadValues function could be reduced to a couple lines of code if you get all data- attributes and iterate the list:

function loadvalues(obj) {
   var dataKeys = obj.data();
   for(var key in dataKeys) {
     settings[key] = dataKeys[key];
   }
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.