Creating a slider without recursion

Given the following jsFiddle, how can I implement the same effect as me without creating on the stack?

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

I tried to do 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 the nodes that are added during the loop.

+4
source share
3 answers

You can run the _cycle() function with 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 .

+5
source

You do not want something to resemble while (true).

Your problem is related to the fact that you are creating a static function, and then trying to figure out how to animate children with the restriction of saving them within your static function.

Instead, you should create an instance of the object for each element so that it maintains the state of the slider and updates it using the implementation necessary for the slider to work.

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(); }); 
+1
source

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

Live Query leverages the power of jQuery selectors by binding events or automatically triggering callbacks for matched elements, even after loading the page and updating the DOM.

For example, you can use the following code to bind the click event to all A tags, even to any A tags that you can add through AJAX.

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

Source: https://habr.com/ru/post/1369252/


All Articles