-
-
Save remy/2484402 to your computer and use it in GitHub Desktop.
/** | |
* author Remy Sharp | |
* url http://remysharp.com/tag/marquee | |
*/ | |
(function ($) { | |
$.fn.marquee = function (klass) { | |
var newMarquee = [], | |
last = this.length; | |
// works out the left or right hand reset position, based on scroll | |
// behavior, current direction and new direction | |
function getReset(newDir, marqueeRedux, marqueeState) { | |
var behavior = marqueeState.behavior, width = marqueeState.width, dir = marqueeState.dir; | |
var r = 0; | |
if (behavior == 'alternate') { | |
r = newDir == 1 ? marqueeRedux[marqueeState.widthAxis] - (width*2) : width; | |
} else if (behavior == 'slide') { | |
if (newDir == -1) { | |
r = dir == -1 ? marqueeRedux[marqueeState.widthAxis] : width; | |
} else { | |
r = dir == -1 ? marqueeRedux[marqueeState.widthAxis] - (width*2) : 0; | |
} | |
} else { | |
r = newDir == -1 ? marqueeRedux[marqueeState.widthAxis] : 0; | |
} | |
return r; | |
} | |
// single "thread" animation | |
function animateMarquee() { | |
var i = newMarquee.length, | |
marqueeRedux = null, | |
$marqueeRedux = null, | |
marqueeState = {}, | |
newMarqueeList = [], | |
hitedge = false; | |
while (i--) { | |
marqueeRedux = newMarquee[i]; | |
$marqueeRedux = $(marqueeRedux); | |
marqueeState = $marqueeRedux.data('marqueeState'); | |
if ($marqueeRedux.data('paused') !== true) { | |
// TODO read scrollamount, dir, behavior, loops and last from data | |
marqueeRedux[marqueeState.axis] += (marqueeState.scrollamount * marqueeState.dir); | |
// only true if it's hit the end | |
hitedge = marqueeState.dir == -1 ? marqueeRedux[marqueeState.axis] <= getReset(marqueeState.dir * -1, marqueeRedux, marqueeState) : marqueeRedux[marqueeState.axis] >= getReset(marqueeState.dir * -1, marqueeRedux, marqueeState); | |
if ((marqueeState.behavior == 'scroll' && marqueeState.last == marqueeRedux[marqueeState.axis]) || (marqueeState.behavior == 'alternate' && hitedge && marqueeState.last != -1) || (marqueeState.behavior == 'slide' && hitedge && marqueeState.last != -1)) { | |
if (marqueeState.behavior == 'alternate') { | |
marqueeState.dir *= -1; // flip | |
} | |
marqueeState.last = -1; | |
$marqueeRedux.trigger('stop'); | |
marqueeState.loops--; | |
if (marqueeState.loops === 0) { | |
if (marqueeState.behavior != 'slide') { | |
marqueeRedux[marqueeState.axis] = getReset(marqueeState.dir, marqueeRedux, marqueeState); | |
} else { | |
// corrects the position | |
marqueeRedux[marqueeState.axis] = getReset(marqueeState.dir * -1, marqueeRedux, marqueeState); | |
} | |
$marqueeRedux.trigger('end'); | |
} else { | |
// keep this marquee going | |
newMarqueeList.push(marqueeRedux); | |
$marqueeRedux.trigger('start'); | |
marqueeRedux[marqueeState.axis] = getReset(marqueeState.dir, marqueeRedux, marqueeState); | |
} | |
} else { | |
newMarqueeList.push(marqueeRedux); | |
} | |
marqueeState.last = marqueeRedux[marqueeState.axis]; | |
// store updated state only if we ran an animation | |
$marqueeRedux.data('marqueeState', marqueeState); | |
} else { | |
// even though it's paused, keep it in the list | |
newMarqueeList.push(marqueeRedux); | |
} | |
} | |
newMarquee = newMarqueeList; | |
if (newMarquee.length) { | |
setTimeout(animateMarquee, 25); | |
} | |
} | |
// TODO consider whether using .html() in the wrapping process could lead to loosing predefined events... | |
this.each(function (i) { | |
var $marquee = $(this), | |
width = $marquee.attr('width') || $marquee.width(), | |
height = $marquee.attr('height') || $marquee.height(), | |
$marqueeRedux = $marquee.after('<div ' + (klass ? 'class="' + klass + '" ' : '') + 'style="display: block-inline; width: ' + width + 'px; height: ' + height + 'px; overflow: hidden;"><div style="float: left; white-space: nowrap;">' + $marquee.html() + '</div></div>').next(), | |
marqueeRedux = $marqueeRedux.get(0), | |
hitedge = 0, | |
direction = ($marquee.attr('direction') || 'left').toLowerCase(), | |
marqueeState = { | |
dir : /down|right/.test(direction) ? -1 : 1, | |
axis : /left|right/.test(direction) ? 'scrollLeft' : 'scrollTop', | |
widthAxis : /left|right/.test(direction) ? 'scrollWidth' : 'scrollHeight', | |
last : -1, | |
loops : $marquee.attr('loop') || -1, | |
scrollamount : $marquee.attr('scrollamount') || this.scrollAmount || 2, | |
behavior : ($marquee.attr('behavior') || 'scroll').toLowerCase(), | |
width : /left|right/.test(direction) ? width : height | |
}; | |
// corrects a bug in Firefox - the default loops for slide is -1 | |
if ($marquee.attr('loop') == -1 && marqueeState.behavior == 'slide') { | |
marqueeState.loops = 1; | |
} | |
$marquee.remove(); | |
// add padding | |
if (/left|right/.test(direction)) { | |
$marqueeRedux.find('> div').css('padding', '0 ' + width + 'px'); | |
} else { | |
$marqueeRedux.find('> div').css('padding', height + 'px 0'); | |
} | |
// events | |
$marqueeRedux.bind('stop', function () { | |
$marqueeRedux.data('paused', true); | |
}).bind('pause', function () { | |
$marqueeRedux.data('paused', true); | |
}).bind('start', function () { | |
$marqueeRedux.data('paused', false); | |
}).bind('unpause', function () { | |
$marqueeRedux.data('paused', false); | |
}).data('marqueeState', marqueeState); // finally: store the state | |
// todo - rerender event allowing us to do an ajax hit and redraw the marquee | |
newMarquee.push(marqueeRedux); | |
marqueeRedux[marqueeState.axis] = getReset(marqueeState.dir, marqueeRedux, marqueeState); | |
$marqueeRedux.trigger('start'); | |
// on the very last marquee, trigger the animation | |
if (i+1 == last) { | |
animateMarquee(); | |
} | |
}); | |
return $(newMarquee); | |
}; | |
}(jQuery)); |
Isn't it display: inline-block instead of display: block-inline?
Hi! How can I change gap between elements. Example: I have 2 elements in row and I wanna let the first act like 3rd. So first go automatically after 2nd without waiting till everything finish?
Thanks
I'm using this gistfile to smooth out my marquees, and it's working great!
What's needed to be able to handle the "onfinish" event? Thanks!
Hi!, the plugin is so cool, but there is a bug, the marquee is not responsive if the window width is changed. Could you solve this bug?
@HuanxinHu
I just found myself looking for a solution to the same thing. I have a feeling a custom jquery function will have to be implemented to resize and change the padding.
I have found a bug in this code. On line 100, you see the style "display: block-inline;". That is actually backwards. It should be "display: inline-block;"
@aamirafridi - the updated URL is https://github.com/aamirafridi/jQuery.Marquee - currently 360 stars.
Even with CSS3, you still need to calculate the speed.
Thanks for this! I tweaked it slightly to support % width and height on the marquee element: https://gist.github.com/floatplane/6226786