A few points:
$(this).html('')
will throw away the contents of #div1
(on the first iteration) and #div2
(on the second iteration). If you want the marquee to loop, that's not going to work.
- This is a perfect use case for a simple jQuery plugin (see the documentation).
- You should probably use
next()
instead of the eq
selector, to make your code work with any number of children (or at least any number above 1).
- To stop the animations on hover, you'll have to call
stop()
on any elements that may be half-way into an animation. Pausing and continuing the marquee would be good use cases for plugin methods.
- You could consider using the
position
and top
attributes to position the children; this is exactly what position: absolute
is for.
Given below is an example of a simple plugin that does roughly what you want. To keep in theme with this site, I've stuck with your approach -- animation is done on margin-top
and, as you can see, only the first child is animated.
Because of this, the marquee won't loop until all children are outside the parent div
. To make it wrap sooner, I would advise rewriting the plugin to use position: absolute
and the top
attribute on each child. That way, each child can be idependently animated and the marquee can be looped earlier.
Finally, keep in mind that this example is far from perfect. For example, the total height of the children is re-calculated on each run. The plugin could be made more efficient simply by maintaining state.
Plugin:
(function($) {
var methods = {
init: function(options) {
this.children(':first').stop();
this.marquee('play');
},
play: function() {
var marquee = this,
pixelsPerSecond = 100,
firstChild = this.children(':first'),
totalHeight = 0,
difference,
duration;
// Find the total height of the children by adding each child's height:
this.children().each(function(index, element) {
totalHeight += $(element).innerHeight();
});
// The distance the divs have to travel to reach -1 * totalHeight:
difference = totalHeight + parseInt(firstChild.css('margin-top'), 10);
// The duration of the animation needed to get the correct speed:
duration = (difference/pixelsPerSecond) * 1000;
// Animate the first child's margin-top to -1 * totalHeight:
firstChild.animate(
{ 'margin-top': -1 * totalHeight },
duration,
'linear',
function() {
// Move the first child back down (below the container):
firstChild.css('margin-top', marquee.innerHeight());
// Restart whole process... :)
marquee.marquee('play');
}
);
},
pause: function() {
this.children(':first').stop();
}
};
$.fn.marquee = function(method) {
// Method calling logic
if (methods[method]) {
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
} else if (typeof method === 'object' || !method) {
return methods.init.apply(this, arguments);
} else {
$.error('Method ' + method + ' does not exist on jQuery.marquee');
}
};
})(jQuery);
Usage:
var marquee = $('#mydiv');
marquee.marquee();
marquee.hover(function() {
marquee.marquee('pause');
}, function() {
marquee.marquee('play');
});
This example can also be found on jsfiddle: http://jsfiddle.net/PPvG/LgsrU/