diff options
Diffstat (limited to 'public/marquee.js')
| -rw-r--r-- | public/marquee.js | 155 | 
1 files changed, 155 insertions, 0 deletions
| diff --git a/public/marquee.js b/public/marquee.js new file mode 100644 index 0000000..9e046d5 --- /dev/null +++ b/public/marquee.js @@ -0,0 +1,155 @@ +/** +* 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));
\ No newline at end of file | 
