chrism4111 Δημοσ. 26 Αυγούστου 2014 Δημοσ. 26 Αυγούστου 2014 Γεια σας παίδες....Έχω ένα θεματάκι με ένα jquery.plugin (slider) που φτιάχνω.Γενικά έχω ξεκινήσει να φτιάχνω τα προσωπικά μου tools με τα οποία θα παίζω σε κάθε μου δουλειά.Το θέμα στην περίπτωση αυτή είναι ένας jQuery slider και το χάσιμο μέσα στα instances του slider.Ας ξεκινήσω με ένα κομμάτι κώδικα: $.slider = function(){ _init: function(){ this._initEvents(); }, _initEvents : function(){ this.$startPauseButton.on('click.container', $.proxy(this._startPauseToggleSlider, this)); }, _startPauseToggleSlider: function(){ if(this.isPlay === true){ this.__timer.clear(this); return ; } this.timerId = this.__timer.resume(); }, __timer: { start: function(that){ return setTimeout(..., delay) }, resume: function(){ return this.start()// generate remaining time and start new timer} clear: function(that){ window.clearTimeout(that.timerId) } } } Η μέθοδος _init τρέχει μία φόρα στο πρόγραμμα και είναι o constructor Κάποια στιγμή στο παραπάνω κώδικα χάνω το timerId και έτσι δεν μπορώ να κάνω Pause - Resume τον slider..Αυτό το bug το εντόπισα όταν έτρεξα το παρακάτω$('#sliderContainer').slider({/*some options*/});$('#slider2Container').slider({/*some options*/});Δηλαδή όταν έβαλα 2 sliders μέσα στην σελίδα.Νομίζω ότι εφόσον κάνει bind ο Proxy την μέθοδο _startPauseSlider κατά το click τότε το current instance περνάει σαν ένα απλό var στην μέθοδο και μετά λειτουργεί σαν ένα διαφορετικό (fake) instance.Έτσι την επόμενη φορά που θα πατηθεί το κουμπί για να σταματήσει ο Slider το πρόγραμμα δεν θα έχει το ενημερωμένο id του timer.Έχει κανείς καμία ιδέα για το πως θα λύσω το προβλημα αυτό?Έχω σκεφτεί να χρησιμοποιήσω global vars έξω από το plugin αλλά θα ήθελα να έιναι η τελευταία μου λύση αυτό.* Τον κώδικα τον έγραψα τώρα αν έχω κάνει κανένα λάθος συγχωρέστε
defacer Δημοσ. 27 Αυγούστου 2014 Δημοσ. 27 Αυγούστου 2014 Δείξε λίγο παραπάνω κώδικα. Πρώτον μιλάμε για jQuery plugin και όχι jQuery UI widget έτσι; Δεύτερον μιλάμε για υποστήριξη πολλαπλών instances -- αν δε χρησιμοποιείς κάποιο per-instance storage δεν είναι δυνατόν να δουλέψει. Τυπικά αυτό που κάνουν τα plugins είναι να αποθηκεύουν την όποια per-instance πληροφορία τους χρειάζεται στο $(targetElement).data(), κάνε και συ το ίδιο. 1
chrism4111 Δημοσ. 27 Αυγούστου 2014 Μέλος Δημοσ. 27 Αυγούστου 2014 Δείξε λίγο παραπάνω κώδικα. Πρώτον μιλάμε για jQuery plugin και όχι jQuery UI widget έτσι; Δεύτερον μιλάμε για υποστήριξη πολλαπλών instances -- αν δε χρησιμοποιείς κάποιο per-instance storage δεν είναι δυνατόν να δουλέψει. Τυπικά αυτό που κάνουν τα plugins είναι να αποθηκεύουν την όποια per-instance πληροφορία τους χρειάζεται στο $(targetElement).data(), κάνε και συ το ίδιο. Είναι καθαρά Jquery Plugin και όχι jQuery.UI plugin Απλά χρησιμοποιώ το velocityjs ή το gsap κατ' επιλογή για να κάνω accelerate τα animations.. Θα κάνω share τον κώδικα μόλις γυρίσω από την δουλειά κατά τις 8 - 9 η ώρα...
chrism4111 Δημοσ. 27 Αυγούστου 2014 Μέλος Δημοσ. 27 Αυγούστου 2014 (επεξεργασμένο) Στην _initEvents έχω το πρόβλημα με τo startStopButtonΕδώ είναι το js για τον slider ;(function($, window, undefined){ 'use strict'; $.chSlider = function(option, element){ this.$el = $( element ); if(this.$el.attr('data-options')){ $.chSlider.defaults = $.extend(true, {}, $.chSlider.defaults, $.parseJSON(this.$el.data('options').replace(/'/g,"\""))); } this._init(); } $.chSlider.defaults = { animationEngine: 'jquery', height: '450', // Mixed Var - String and Int easing: 'easeInSine', autoplay: false, transitionDelay: 600, navigation: true, delay: 10000, loadingBar: true, startStopButton: { active: true, start: 'Start', stop: 'Pause' }, theme: 'grayscale' }; $.chSlider.prototype = { _init: function( options ){ this.options = $.extend( true, {}, $.chSlider.defaults, options); // Generate some cache storage and some init actions this._generateCache(); // Initialize Events this._initEvents(); if(this.options.autoplay === true){ this._autoplaySlider(); } }, getDelay: function(){ return this.options.delay; }, _generateCache: function(){ // Target container this.$container = this.$el; // The ul list this.$list = this.$container.children('div').children( 'ul' ); // The list items this.$items = this.$list.children('li'); // The div inside container and parent of ul this.$inner = this.$list.parent('div'); // The number of list items this.itemsCount = this.$items.length; // The current number of li this.current = 0; // The prev active slide of current this.old = 0; // If is current animated this.isAnimating = false; // Create and render the buttons, navigation, loading bars etc if(this.itemsCount > 1){ this.$navPrev = $( '<span class="fws-prev"><</span>' ).hide(); this.$navNext = $( '<span class="fws-next">></span>' ); if(this.options.navigation === true){ $( '<nav class="fws-nav" />' ).append( this.$navPrev, this.$navNext ).appendTo( this.$container ); } if(this.options.autoplay === true && this.options.startStopButton.active === true){ this.$startStopButton = $( '<span class="fws-startstopButton">' + this.options.startStopButton.stop + '</span>'); this.$container.append(this.$startStopButton); } if(this.options.autoplay === true && this.options.loadingBar === true){ this.$loadingBar = $('<div class="fws-loading-container"></div>'); this.$loadingBarInner = $('<div class="fws-loading-inner"></div>'); this.$loadingBar.append(this.$loadingBarInner).appendTo(this.$container); } } switch (this.options.animationEngine){ case 'jquery' : break; case 'velocityjs' : break; case 'gsap' : break; default : this.options.animationEngine = 'jquery'; break; } // Some Init Css Actions this.$container.addClass('fullSliderContainer fws-' + this.options.theme); this.$inner.addClass('fullSliderInner'); this.$container.css('height', this.options.height); this.$list.css('width', this.itemsCount * 100 + '%'); this.$items.css('width', 100 / this.itemsCount + '%'); var maxHeight = 0; var self = this; var count = this.itemsCount; this.$items.each(function(){ var $this = $(this), src = $this.attr('data-background'); if(src){ var image = new Image(); image.onload = function(){ $this.css( 'background-image', 'url(' + src + ')' ); $this.css( 'background-repeat', 'no-repeat' ); $this.css( 'background-size', 'cover' ); var center = ($this.attr('data-center')) ? $this.attr('data-center') : 'center center'; $this.css( 'background-position', center ); }; image.src = src; } }); this.$items.css('height', this.options.height + 'px'); }, _initEvents: function(){ var self = this; if(this.itemsCount > 1){ // Nav Click this.$navPrev.on('click.fullSliderContainer', $.proxy(this._navigate, this, 'prev')); this.$navNext.on('click.fullSliderContainer', $.proxy(this._navigate, this, 'next')); if(this.options.startStopButton.active === true){ this.$startStopButton.on('click.fullSliderContainer', $.proxy(this._pauseResumeAction, this)); } //if(this.options.hoverPause === true){ // this.$container.on('mouseenter.fullSliderContainer', $.proxy(this._pause, this)); // this.$container.on('mouseleave.fullSliderContainer', $.proxy(this._resume, this)); //} // Dots } }, _navigate: function( direction ){ // Navigate event if(this.isAnimating){ return false; } this.isAnimating = true; this.old = this.current; this.isStop = false; if(direction === 'next' && this.current < this.itemsCount - 1){ ++this.current; } if(direction === 'prev' && this.current > 0){ --this.current; } this._slide(); }, _pauseResumeAction: function(){ if(this.isStop === true){ this._resume(); return ; } else{ this._pause(); } }, _pause: function(){ this.isStop = true; this.loadingBarInstance = this.$loadingBarInner.width(); if(this.options.startStopButton.active === true){ this._toggleStartStopButton(); } if(this.options.animationEngine === 'velocityjs'){ this.$loadingBarInner.velocity('stop'); }else if(this.options.animationEngine === 'jquery'){ this.$loadingBarInner.clearQueue().stop().css('width', this.loadingBarInstance + 'px'); }else if(this.options.animationEngine === 'gsap'){ if(!this.tweenMaxLoadingAnimation.paused()){ this.tweenMaxLoadingAnimation.pause(); } } console.log(this.$container.attr('id') + ' ' + this.timerId + ' Pause'); this.__timer.pause(this.timerId); this.remainingTime = this.__timer.getRemainingTime(); }, _resume: function(){ this.isStop = false; if(this.options.startStopButton.active === true){ this._toggleStartStopButton(); } if(this.options.animationEngine === 'velocityjs'){ this.$loadingBarInner.velocity({width: '100%'}, this.remainingTime, this.options.easing); }else if(this.options.animationEngine === 'jquery'){ this.$loadingBarInner.animate({width: '100%'}, this.remainingTime, this.options.easing); }else if(this.options.animationEngine === 'gsap'){ if(this.tweenMaxLoadingAnimation.paused()){ this.tweenMaxLoadingAnimation.resume(); } } this.timerId = this.__timer.resume(true); }, _toggleStartStopButton: function(){ switch (this.isStop){ case false: this.$startStopButton.text(this.options.startStopButton.stop); break; case true: this.$startStopButton.text(this.options.startStopButton.start); break; } }, _slide: function(){ this._toggleNavControls(); var translateVal = -1 * this.current * 100 / this.itemsCount; if(this.options.animationEngine === 'velocityjs'){ this.$list.velocity({marginLeft: -1 * this.current * 100 + '%'}, this.options.transitionDelay, this.options.easing ); }else if(this.options.animationEngine === 'jquery'){ this.$list.animate({marginLeft: -1 * this.current * 100 + '%'}, this.options.transitionDelay, this.options.easing ); }else if(this.options.animationEngine === 'gsap'){ TweenMax.to(this.$list, this.options.transitionDelay / 1000, {marginLeft: -1 * this.current * 100 + '%', ease: this.options.easing}); } var transitionendfn = $.proxy( function(){ this.isAnimating = false; }, this); if(this.options.autoplay === true){ this._clearAutoplaySlider(); } transitionendfn.call(); }, _jump : function( position ){ if(position === this.current || this.isAnimating){ return false; } this.isAnimating = false; this.old = this.current; this.current = position; this._slide(); }, _toggleNavControls: function(){ switch(this.current){ case 0: this.$navNext.show(); this.$navPrev.hide(); break; case this.itemsCount - 1 : this.$navNext.hide(); this.$navPrev.show(); break; default : this.$navNext.show(); this.$navPrev.show(); break; } }, _autoplaySlider: function(){ if(this.options.loadingBar === true){ this._loadingBarResetAnimation(); this._loadingBarStartAnimation(); } this.timerId = this.__timer.start( $.proxy(this._autoplaySliderStart, this), this.options.delay + this.options.transitionDelay, this.$container.attr('id') ); console.log(this.$container.attr('id') + ' ' + this.timerId); }, _clearAutoplaySlider: function(){ this.__timer.clear(this.timerId); // Clear timeout this._autoplaySlider(); }, _autoplaySliderStart: function(){ if(this.itemsCount - 1 > this.current){ this._jump(this.current + 1); }else{ this._jump(0); } }, _loadingBarStartAnimation: function(){ if(this.options.animationEngine === 'velocityjs'){ this.$loadingBarInner.velocity({width: '100%'}, this.options.delay + this.options.transitionDelay, this.options.easing); }else if(this.options.animationEngine === 'jquery'){ this.$loadingBarInner.animate({width: '100%'}, this.options.delay + this.options.transitionDelay, this.options.easing); }else if(this.options.animationEngine === 'gsap'){ this.tweenMaxLoadingAnimation = new TweenMax.to(this.$loadingBarInner, (this.options.delay + this.options.transitionDelay) / 1000, {width: '100%', ease: this.options.easing}); } }, _loadingBarResetAnimation: function(){ if(this.options.animationEngine === 'velocityjs'){ this.$loadingBarInner.velocity('stop').css({width: '0%'}); }else if(this.options.animationEngine === 'jquery'){ this.$loadingBarInner.clearQueue().stop().css({width: '0%'}); }else if(this.options.animationEngine === 'gsap'){ if(this.tweenMaxLoadingAnimation){ this.tweenMaxLoadingAnimation.kill(); this.$loadingBarInner.css({width: '0%'}); } } }, __timer: { start: function(callback, delay, id){ this.timerId = null; this.callback = callback; this.delay = delay; this.pauseDate = null; this.startDate = new Date(); this.resume(false); return this.timerId; }, getRemainingTime : function(){ var pauseTime, startTime; if(this.startDate){ startTime = this.startDate.getTime(); } if(this.pauseDate){ pauseTime = this.pauseDate.getTime(); } return this.delay - ( pauseTime - startTime ); }, pause: function(id){ window.clearTimeout(id); this.pauseDate = new Date(); }, resume: function(remainingTime){ var delay = remainingTime ? this.getRemainingTime() : this.delay; this.timerId = window.setTimeout(this.callback, delay); return this.timerId; }, clear: function(id){ window.clearTimeout(id); } }, destroy: function(){ if(this.itemsCount > 1){ this.$navPrev.parent().remove(); } this.$list.css('width', 'auto'); this.$items.css('width', 'auto'); } }; $.fn.chSlider = function(options){ this.each(function(){ var instance = $.data(this, 'fullWidthContainer'); if(instance){ instance._init(); }else{ instance = $.data(this, 'fullWidthContainer', new $.chSlider(options, this)); } }); return this; }; })(jQuery, window); Εδώ το html <div id="fullSlider" class="fsContainer" data-options="{'height':200, 'animationEngine':'gsap', 'easing':'easeInOutQuint', 'transitionDelay':1200, 'autoplay': true}"> <div> <ul> <li data-background="images/1.jpg" data-center="center center"><a href="#">aaa</a></li> <li data-background="images/2.png"><a href="#">acc</a></li> <li data-background="images/3.jpg"><a href="#">av</a></li> </ul> </div> </div> <div id="fullSlider2" class="fsContainer" data-options="{'height':200, 'animationEngine':'jquery', 'easing':'easeInOutQuint', 'transitionDelay':1200, 'autoplay': true}"> <div> <ul> <li data-background="images/1.jpg" data-center="center center"><a href="#">aaa</a></li> <li data-background="images/2.png"><a href="#">acc</a></li> <li data-background="images/3.jpg"><a href="#">av</a></li> </ul> </div> </div> <div id="fullSlider3" class="fsContainer" data-options="{'height':200, 'animationEngine':'velocityjs', 'easing':'easeInOutQuint', 'transitionDelay':1200, 'autoplay': true}"> <div> <ul> <li data-background="images/1.jpg" data-center="center center"><a href="#">aaa</a></li> <li data-background="images/2.png"><a href="#">acc</a></li> <li data-background="images/3.jpg"><a href="#">av</a></li> </ul> </div> </div> <script> (function($){ $('#fullSlider, #fullSlider2, #fullSlider3').chSlider(); })(jQuery); </script> Και εδώ το css .fullSliderContainer{ position: relative; margin: 0 0 10px; overflow: hidden; padding: 0px 0 0px; } .fullSliderContainer ul{ margin: 0; padding: 0; white-space: nowrap; list-style-type: none; } .fullSliderContainer ul li{ float: left; display: block; margin: 0; padding: 0; position: relative; } .fullSliderContainer ul li > a, .fullSliderContainer ul li > div { display: block; text-align: center; outline: none; } .fullSliderContainer ul li > a img { border: none; display: block; margin: 0 auto; max-width: 75%; } .fullSliderContainer nav span { position: absolute; bottom: 10px; width: 30px; height: 30px; line-height: 30px; font-size: 20px; text-align: center; margin-top: -50px; cursor: pointer; font-weight: normal; } .fullSliderContainer nav span.fws-next { right: 0px; } .fullSliderContainer nav span.fws-prev { left: 0px; } .fws-startstopButton{ position: absolute; bottom: 10px; right: 32px; width: 100px; height: 30px; line-height: 30px; text-align: center; cursor: pointer; } .fws-loading-container{ position: absolute; width: 100%; height: 10px; bottom: 0px; left: 0px; } .fws-loading-inner{ position: relative; width: 0%; height: 10px; } /* Themes */ .fullSliderContainer.fws-grayscale nav span{ background: rgba(255,255,255, 0.6); color: rgba(0, 0, 0, 0.6); } .fullSliderContainer.fws-grayscale nav span:hover{ background: rgba(0, 0, 0, 0.6); color: rgba(255,255,255, 0.6); } .fws-loading-container{ background: rgba(255,255,255, 0.6); } .fws-loading-inner{ background: rgba(0, 0, 0, 0.6); } .fws-startstopButton{ background: rgba(255,255,255, 0.6); color: rgba(0, 0, 0, 0.6); } Επεξ/σία 27 Αυγούστου 2014 από chrism4111
Προτεινόμενες αναρτήσεις
Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε
Πρέπει να είστε μέλος για να αφήσετε σχόλιο
Δημιουργία λογαριασμού
Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!
Δημιουργία νέου λογαριασμούΣύνδεση
Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.
Συνδεθείτε τώρα