不用递归制作滑块

发布于 2024-12-01 22:27:12 字数 6794 浏览 2 评论 0原文

给定以下 jsFiddle,如何在不构建堆栈的情况下实现与我所做的相同的效果?

http://jsfiddle.net/YWMcy/1/

我尝试做这样的事情:

jQuery(document).ready(function () {
    'use strict';
    (function ($) {

        function validateOptions(options) {
            if (typeof(options.delay) == typeof(0)) {
                $.error('Delay value must an integer.');
                return false;
            } else if (options.delay < 0) {
                $.error('Delay value must be greater than zero.');
                return false;
            }

            if (typeof(options.direction) == typeof('')) {
                $.error('Direction value must be a string.');
                return false;
            } else if (!(options.direction in ['left', 'right', 'up', 'down'])) {
                $.error('Direction value must be "left", "right", "up", or "down".');
                return false;
            }

            if (typeof(options.easing) == typeof('')) {
                $.error('Easing value must be a string.');
                return false;
            }

            if (typeof(options.selector) == typeof('')) {
                $.error('Selector value must be a string.');
                return false;
            }

            if (options.transition < 0) {
                $.error('Transition value must be greater than zero.');
                return false;
            }
            return true;
        }

        var methods = {
            init:   function (options) {

                return this.each(function () {

                    var settings = {
                        delay:      5000,
                        direction:  'left',
                        easing:     'swing',
                        selector:   '*',
                        transition: 3000
                    };

                    if (options) {
                        $.extend(settings, options);
                    }

                    $(this).css({
                        overflow:   'hidden',
                        position:   'relative'
                    });

                    var styles = {
                        left:       0,
                        position:   'absolute',
                        top:        0
                    };

                    switch (settings.direction) {
                    case 'left':
                        styles.left = $(this).width() + 'px';
                        break;
                    case 'right':
                        styles.left = -$(this).width() + 'px';
                        break;
                    case 'up':
                        styles.top = $(this).height() + 'px';
                        break;
                    case 'down':
                        styles.top = -$(this).height() + 'px';
                        break;
                    default:
                        jQuery.error('Direction ' + settings.direction + ' is not valid for jQuery.fn.cycle');
                        break;
                    }

                    $(this).children(settings.selector).css(styles).first().css({
                        left:   0,
                        top:    0
                    });

                    if ($(this).children(settings.selector).length > 1) {
                        $(this).cycle('slide', settings);
                    }
                });
            },

            slide:  function (options) {
                return this.each(function () {

                    var settings = {
                        delay:      5000,
                        direction:  'left',
                        easing:     'swing',
                        selector:   '*',
                        transition: 3000
                    }, animation, property, value;

                    if (options) {
                        $.extend(settings, options);
                    }

                    switch (settings.direction) {
                    case 'left':
                        animation = {left: '-=' + $(this).width()};
                        property = 'left';
                        value = $(this).width();
                        break;
                    case 'right':
                        animation = {left: '+=' + $(this).width()};
                        property = 'left';
                        value = -$(this).width();
                        break;
                    case 'up':
                        animation = {top: '-=' + $(this).height()};
                        property = 'top';
                        value = $(this).height();
                        break;
                    case 'down':
                        animation = {top: '+=' + $(this).height()};
                        property = 'top';
                        value = -$(this).height();
                        break;
                    default:
                        jQuery.error('Direction ' + settings.direction + ' is not valid for jQuery.fn.cycle');
                        break;
                    }

                    $(this).children(settings.selector + ':first-child').each(function () {
                        $(this).delay(settings.delay);
                        $(this).animate(
                            animation,
                            settings.transition,
                            settings.easing,
                            function () {
                                $(this).css(property, value);
                            }
                        );
                    });

                    $(this).append($(this).children(settings.selector + ':first-child').detach());

                    $(this).children(settings.selector + ':first-child').each(function () {
                        $(this).delay(settings.delay);
                        $(this).animate(
                            animation,
                            settings.transition,
                            settings.easing,
                            function () {
                            $(this).parent().cycle('slide', settings);
                            }
                        );
                    });
                });
            }
        };

        jQuery.fn.cycle = function (method, options) {
            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.fn.cycle');
            }
        };
    }(jQuery));

    jQuery('.slider').cycle();

});

但是 < code>each() 方法不考虑循环期间添加的节点。

Given the following jsFiddle, how can I implement the same effect as I have made without building on the stack?

http://jsfiddle.net/YWMcy/1/

I tried doing something like this:

jQuery(document).ready(function () {
    'use strict';
    (function ($) {

        function validateOptions(options) {
            if (typeof(options.delay) == typeof(0)) {
                $.error('Delay value must an integer.');
                return false;
            } else if (options.delay < 0) {
                $.error('Delay value must be greater than zero.');
                return false;
            }

            if (typeof(options.direction) == typeof('')) {
                $.error('Direction value must be a string.');
                return false;
            } else if (!(options.direction in ['left', 'right', 'up', 'down'])) {
                $.error('Direction value must be "left", "right", "up", or "down".');
                return false;
            }

            if (typeof(options.easing) == typeof('')) {
                $.error('Easing value must be a string.');
                return false;
            }

            if (typeof(options.selector) == typeof('')) {
                $.error('Selector value must be a string.');
                return false;
            }

            if (options.transition < 0) {
                $.error('Transition value must be greater than zero.');
                return false;
            }
            return true;
        }

        var methods = {
            init:   function (options) {

                return this.each(function () {

                    var settings = {
                        delay:      5000,
                        direction:  'left',
                        easing:     'swing',
                        selector:   '*',
                        transition: 3000
                    };

                    if (options) {
                        $.extend(settings, options);
                    }

                    $(this).css({
                        overflow:   'hidden',
                        position:   'relative'
                    });

                    var styles = {
                        left:       0,
                        position:   'absolute',
                        top:        0
                    };

                    switch (settings.direction) {
                    case 'left':
                        styles.left = $(this).width() + 'px';
                        break;
                    case 'right':
                        styles.left = -$(this).width() + 'px';
                        break;
                    case 'up':
                        styles.top = $(this).height() + 'px';
                        break;
                    case 'down':
                        styles.top = -$(this).height() + 'px';
                        break;
                    default:
                        jQuery.error('Direction ' + settings.direction + ' is not valid for jQuery.fn.cycle');
                        break;
                    }

                    $(this).children(settings.selector).css(styles).first().css({
                        left:   0,
                        top:    0
                    });

                    if ($(this).children(settings.selector).length > 1) {
                        $(this).cycle('slide', settings);
                    }
                });
            },

            slide:  function (options) {
                return this.each(function () {

                    var settings = {
                        delay:      5000,
                        direction:  'left',
                        easing:     'swing',
                        selector:   '*',
                        transition: 3000
                    }, animation, property, value;

                    if (options) {
                        $.extend(settings, options);
                    }

                    switch (settings.direction) {
                    case 'left':
                        animation = {left: '-=' + $(this).width()};
                        property = 'left';
                        value = $(this).width();
                        break;
                    case 'right':
                        animation = {left: '+=' + $(this).width()};
                        property = 'left';
                        value = -$(this).width();
                        break;
                    case 'up':
                        animation = {top: '-=' + $(this).height()};
                        property = 'top';
                        value = $(this).height();
                        break;
                    case 'down':
                        animation = {top: '+=' + $(this).height()};
                        property = 'top';
                        value = -$(this).height();
                        break;
                    default:
                        jQuery.error('Direction ' + settings.direction + ' is not valid for jQuery.fn.cycle');
                        break;
                    }

                    $(this).children(settings.selector + ':first-child').each(function () {
                        $(this).delay(settings.delay);
                        $(this).animate(
                            animation,
                            settings.transition,
                            settings.easing,
                            function () {
                                $(this).css(property, value);
                            }
                        );
                    });

                    $(this).append($(this).children(settings.selector + ':first-child').detach());

                    $(this).children(settings.selector + ':first-child').each(function () {
                        $(this).delay(settings.delay);
                        $(this).animate(
                            animation,
                            settings.transition,
                            settings.easing,
                            function () {
                            $(this).parent().cycle('slide', settings);
                            }
                        );
                    });
                });
            }
        };

        jQuery.fn.cycle = function (method, options) {
            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.fn.cycle');
            }
        };
    }(jQuery));

    jQuery('.slider').cycle();

});

But the each() method does not take into account nodes that are added during the loop.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

坚持沉默 2024-12-08 22:27:12

您可以通过 setInterval() 启动您的 _cycle() 函数,以定期更新滑块:

setInterval(function() {
  _cycle2(slider, transition_duration, easing);
}, delay_duration);

请注意,我重命名了您原来的 _cycle() 函数到 _cycle2(),并删除了 delay_duration 参数。您可以在此处查看工作演示

You can launch your _cycle() function through setInterval(), to periodically update the slider:

setInterval(function() {
  _cycle2(slider, transition_duration, easing);
}, delay_duration);

Note that I renamed your original _cycle() function to _cycle2(), and removed the delay_duration parameter. You can see a working demo here.

牵你的手,一向走下去 2024-12-08 22:27:12

你不想要类似 while(true) 的东西。

您的问题源于这样一个事实:您正在创建一个静态函数,然后尝试弄清楚如何在将其全部保留在静态函数范围内的约束下为子级设置动画。

相反,您应该为每个元素创建一个对象的实例,让该对象维护滑块的状态,并让它通过滑块操作所需的实现来更新该状态。

http://jsfiddle.net/qjVJF/3/

    (function ($) {
    var $b = $.behaviors || {};

    $b.slider = function(element, options) {
        this.element = $(element);
        this.panels = this.element.find('.slide');
        this.options = $.extend({}, $b.slider.defaults, options);

        this.currentPanel = 0;
        var horizontal = (this.options.direction == 'left' || this.options.direction == 'right');
        var anti = (this.options.direction == 'left' || this.options.direction == 'up');
        var distance  = horizontal ? '600' : '150';

        this.action = anti ? '-='+distance : '+='+distance;
        this.origin = anti ? distance : 0-distance;
        this.edge = horizontal ? 'left' : 'top';
        this.animation = horizontal ? { "left": this.action } : { "top" : this.action };

        this.panels.css(this.edge, this.origin+'px').show().first().css(this.edge, '0px');

        this.delayNext();
        return this;
    }
    $b.slider.defaults = {
        delay:      500,
        direction:  'left',
        easing:     'swing',
        transition: 3000
    };

    $b.slider.prototype = {
        delayNext: function() {
            setTimeout($.proxy(this.slideNext, this), this.options.delay);
        },
        slideNext: function() { 
            var current = this.panels[this.currentPanel % this.panels.length]; 
            var next = $(this.panels[++this.currentPanel % this.panels.length])
                .css(this.edge, this.origin+'px'); 

            var plugin = this;
            next.add(current).animate(
                this.animation,
                this.options.transition, 
                this.options.easing, 
                function() { 
                    if (this == current) plugin.delayNext();
                }
            );
        }  
    };

    $.fn.cycle = function (options) {
            return this.each(function() { 
                    $(this).data('bCycle', new $b.slider(this, options));
                });
    };
    }(jQuery));

    jQuery(document).ready(function () {
        jQuery('.slider').cycle();
    });

You don't want anything resembling while(true).

Your problem stems from the fact that you're creating a static function and then trying to figure out how to animate the children with the constraint of keeping it all in scope of your static function.

You should instead create an instance of an object per element, let the object maintain the state of the slider and have it update that state via an implementation necessary for the slider to operate.

http://jsfiddle.net/qjVJF/3/

    (function ($) {
    var $b = $.behaviors || {};

    $b.slider = function(element, options) {
        this.element = $(element);
        this.panels = this.element.find('.slide');
        this.options = $.extend({}, $b.slider.defaults, options);

        this.currentPanel = 0;
        var horizontal = (this.options.direction == 'left' || this.options.direction == 'right');
        var anti = (this.options.direction == 'left' || this.options.direction == 'up');
        var distance  = horizontal ? '600' : '150';

        this.action = anti ? '-='+distance : '+='+distance;
        this.origin = anti ? distance : 0-distance;
        this.edge = horizontal ? 'left' : 'top';
        this.animation = horizontal ? { "left": this.action } : { "top" : this.action };

        this.panels.css(this.edge, this.origin+'px').show().first().css(this.edge, '0px');

        this.delayNext();
        return this;
    }
    $b.slider.defaults = {
        delay:      500,
        direction:  'left',
        easing:     'swing',
        transition: 3000
    };

    $b.slider.prototype = {
        delayNext: function() {
            setTimeout($.proxy(this.slideNext, this), this.options.delay);
        },
        slideNext: function() { 
            var current = this.panels[this.currentPanel % this.panels.length]; 
            var next = $(this.panels[++this.currentPanel % this.panels.length])
                .css(this.edge, this.origin+'px'); 

            var plugin = this;
            next.add(current).animate(
                this.animation,
                this.options.transition, 
                this.options.easing, 
                function() { 
                    if (this == current) plugin.delayNext();
                }
            );
        }  
    };

    $.fn.cycle = function (options) {
            return this.each(function() { 
                    $(this).data('bCycle', new $b.slider(this, options));
                });
    };
    }(jQuery));

    jQuery(document).ready(function () {
        jQuery('.slider').cycle();
    });
纵山崖 2024-12-08 22:27:12

也许这个插件 http://docs.jquery.com/Plugins/livequery 可以帮助你?

Live Query 通过绑定事件或自动触发匹配元素的回调来利用 jQuery 选择器的强大功能,即使在页面加载和 DOM 更新之后也是如此。

例如,您可以使用以下代码将点击事件绑定到所有 A 标记,甚至是您可能通过 AJAX 添加的任何 A 标记。

    $('a') 
      .livequery('click', function(event) { 
        alert('clicked'); 
        return false; 
    }); 

Maybe this plugin http://docs.jquery.com/Plugins/livequery can help you?

Live Query utilizes the power of jQuery selectors by binding events or firing callbacks for matched elements auto-magically, even after the page has been loaded and the DOM updated.

For example you could use the following code to bind a click event to all A tags, even any A tags you might add via AJAX.

    $('a') 
      .livequery('click', function(event) { 
        alert('clicked'); 
        return false; 
    }); 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文