2

I am trying to get more object-oriented when writing Javascript for (simple) websites. I want to create a new object, vidyo, for each video element on the page while looping through them. Here's what I have right now. This achieves my goals for the function but I know there has to be a better way to organize this code.

I want to be able to call vidyo on $('video') after the loop. I also want to make it more plugin like, so I could possibly add in options.

I tried making vidyo a legitimate object and tried making new instances of it inside the loop but that didn't work.

Any pointers on how to turn these lines into something more robust? Thanks.

var $win = $(window),
    top = $win.scrollTop(),
    $videos   = $('video');

var vidyo = {
    play: function(video) {
        video[0].play();
    },
    pause: function(video) {
        video[0].pause();
    },
    check: function(vid) {
        var top = $win.scrollTop();
        var videoHeight    = $(vid).outerHeight(true),
            videoHitTop    = $(vid).offset().top,
            videoOffTheTop = videoHeight + videoHitTop;

        if ( top >= videoHitTop && top <= videoOffTheTop ) {
            vidyo.play($(vid));
        } else {
            vidyo.pause($(vid));
        }
    }
}

var checkVideoPosition = function() {
    $videos.each( function( index, el ) {
        vidyo.check(el);
    })
}

$win.on('scroll', checkVideoPosition);
1
  • Are you trying to make Vidyo instances that inherit methods like play, pause, etc. and have an associated video element? If so, you might want to look at how to use constructors. Commented Feb 27, 2015 at 3:50

2 Answers 2

1

MDN has an extremely well-written guide to Object Oriented Programming in Javascript. The links along the left are also very helpful pages to read too. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript

Here's a template to get you started. I won't re-write all your functions for you, I merely intend to steer you in the right direction.

function Vidyo (el) {
    this.element = el && el.tagName === "VIDEO" ? el : document.createElement("video");
}

Vidyo.prototype = {

    play: function() {
        this.element.play();
    },

    pause: function () {
        this.element.pause();
    },

    check: function () {
        // ...
    }
}

var $videos = $("video"),
    vidyos = [];

$videos.each(function (i, el) { vidyos.push( new Vidyo(el) ); });

Hope this helps. I don't know if jQuery has an easier way to get this set up -- I've never used the library. Good luck and have fun!

Sign up to request clarification or add additional context in comments.

Comments

1

Remove all global variables and keep it simple. You don't really need a plugin or a fancy object oriented approach.

$(window).on('scroll', function () {
    var top = $(this).scrollTop(),
        $videos = $('video'),
        $inView = $videos.filter(function () {
            var height = $(this).outerHeight(true),
                hitTop = $(this).offset().top,
                offTheTop = height + hitTop;
            return top >= hitTop && top <= offTheTop;
        });
    $inView.each(function () {
        if (this.paused) this.play();
    });
    $videos.not($inView).each(function () {
        if (!this.paused) this.pause();
    });
});

Edit: you can make this a bit nicer by defining the fixed utility functions in a closure. This way the functions are not re-defined every time the scroll event is being triggered.

$(window).on('scroll', (function () {
    function isInView() {
        var top = $(window).scrollTop(),
            height = $(this).outerHeight(true),
            hitTop = $(this).offset().top,
            offTheTop = height + hitTop;
        return top >= hitTop && top <= offTheTop;
    }
    function playConditionally() {
        if (this.paused) this.play();
    }
    function pauseConditionally() {
        if (!this.paused) this.pause();
    }
    return function () {
        var $videos = $('video'),
            $inView = $videos.filter(isInView);
        $inView.each(playConditionally);
        $videos.not($inView).each(pauseConditionally);
    };
})());

3 Comments

Now there's a beautiful jQuery solution.
There is no need for the second two loops, the first can simply pause or play the video based on the result of the expression used in the return.
@RobG Yes, but a second loop is nicer to read and conveys its meaning instantly. I value that more than saving half a dozen iterations. (Plus, see my additional version - separating concerns allows you to abstract stuff away easily into a closure.)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.