timlckuk-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org
2007-Feb-26 10:39 UTC
Newbie problem, this.options is not defined in member function.
Hi, Very new to prototype/scriptaculous, but I''m working on a client site, and wanted to implement a couple of custom controls. The first one is a slideshow that fades between images. By no means complete yet. I''m having a rather wierd problem though and wondering if anyone can help shed some light on it. In my initialize function I''m setting up a number of member variables, but they don''t seem to exist when called by the PeriodicalExecuter (this.options, this.frontimage, etc). Can someone explain? Here''s the code: Effect.SlideShow = Class.create(); Object.extend(Object.extend(Effect.SlideShow.prototype, Effect.Base.prototype), { // Constructor initialize: function(element) { //alert(''Initializing''); this.element = $(element); this.options = Object.extend({ slidetime: 5, fadetime: 3, height: ''200px'', width: ''200px'', images: new Array() }, arguments[1] || {}); this.frontimage = document.createElement(''div''); this.backimage = document.createElement(''div''); Element.setStyle(this.frontimage, { height:this.options.height, width:this.options.width, position:''absolute'', top:0, left:0 }); Element.setStyle(this.backimage, { height:this.options.height, width:this.options.width, position:''absolute'', top:0, left:0 }); this.element.appendChild(this.backimage); this.element.appendChild(this.frontimage); this.currentbuffer = 0; this.imagecursor = 0; setInterval(''this.shownext'', 5000); this.pe = new PeriodicalExecuter(this.shownext, this.options.slidetime); }, // Show Next Image shownext: function() { //alert(this.frontimage); var hiddenbuffer; var visiblebuffer; if(this.currentbuffer == 0) { hiddenbuffer = this.frontimage; visiblebuffer = this.backimage; } else { hiddenbuffer = this.backimage; visiblebuffer = this.frontimage; } Element.setStyle(hiddenbuffer, {background: "url(" + this.images[this.imagecursor] + ") no-repeat"}); Effect.FadeOut(visiblebuffer); Effect.FadeIn(hiddenbuffer); this.imagecursor++; if(this.imagecursor > this.options.images.length) { this.imagecursor = 0; } } }); --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
Nicolas Terray
2007-Feb-26 11:04 UTC
Re: Newbie problem, this.options is not defined in member function.
On 2/26/07, timlckuk-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org <timlckuk-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> In my initialize function I''m setting up a number of member variables, > but they don''t seem to exist when called by the PeriodicalExecuter > (this.options, this.frontimage, etc). Can someone explain? > > Here''s the code: >[...]> this.pe = new PeriodicalExecuter(this.shownext, > this.options.slidetime); >[...] You have to use this statement instead : this.pe = new PeriodicalExecuter(this.shownext.bind(this), this.options.slidetime); See http://prototypejs.org/api/function/bind for details. Yours, Nicolas Terray --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
Tim Lockwood
2007-Feb-26 11:11 UTC
Re: Newbie problem, this.options is not defined in member function.
> > You have to use this statement instead : > this.pe = new PeriodicalExecuter(this.shownext.bind(this), > this.options.slidetime); > > See http://prototypejs.org/api/function/bind for details. >Thanks Nicolas, that''s got it... Been scratching my head for hours on that one. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
Christophe Porteneuve
2007-Feb-26 13:17 UTC
Re: Newbie problem, this.options is not defined in member function.
Hey there, Your code is rather well done for someone new to Prototype/SAU, and I commend you for it. However, the end of your constructor has me puzzled:> setInterval(''this.shownext'', 5000); > this.pe = new PeriodicalExecuter(this.shownext, > this.options.slidetime);1) Why the heck do you use a setInterval, since you use a PE? This appears to be useless, and will become confusing when you get multiple calls... 2) By passing your shownext method unbound, you lose its "this" meaning when it gets called. At that time, "this" will refer to the default object: the window object. So naturally, you don''t get your fields back. Solution: use a bound call: this.pe = new PeriodicalExecuter(this.shownext.bind(this), this.options.slidetime); For further details and live examples, see: http://prototypejs.org/api/function/bind Your shownext function also has a few issues...> if(this.currentbuffer == 0) {OK, this is true on start, but I fail to see any code, anywhere, that changes this.currentbuffer to be something else. Besides, if you''re just using it as a toggler, use an explicit boolean instead.> Effect.FadeOut(visiblebuffer); > Effect.FadeIn(hiddenbuffer);Proper effect usage mandates creating new effects instead of calling them "statically" like this: new Effect.FadeOut(visiblebuffer); new Effect.FadeIn(hiddenbuffer); ''HTH -- Christophe Porteneuve aka TDD tdd-x+CfDp/qHev2eFz/2MeuCQ@public.gmane.org --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
Tim Lockwood
2007-Feb-26 13:34 UTC
Re: Newbie problem, this.options is not defined in member function.
> Hey there, > > Your code is rather well done for someone new to > Prototype/SAU, and I commend you for it. However, the end of > your constructor has me puzzled:Thanks, I''ve been toying with this framework behind the scenes for a short while now learning from others, but have been doing raw javascript for years. Been a while since I put my JS hat on though so I''m a bit rusty.> > > setInterval(''this.shownext'', 5000); > > this.pe = new PeriodicalExecuter(this.shownext, > > this.options.slidetime); > > 1) Why the heck do you use a setInterval, since you use a PE? > This appears to be useless, and will become confusing when > you get multiple calls... >Yep, useless indeed... Just a leftover from trying various things, removed it just after posting.> 2) By passing your shownext method unbound, you lose its > "this" meaning when it gets called. At that time, "this" > will refer to the default > object: the window object. So naturally, you don''t get your > fields back. > > Solution: use a bound call: > > this.pe = new PeriodicalExecuter(this.shownext.bind(this), > this.options.slidetime); >Nicolas filled me in on that one... I understand now.> For further details and live examples, see: > > http://prototypejs.org/api/function/bind > > Your shownext function also has a few issues... > > > if(this.currentbuffer == 0) { > > OK, this is true on start, but I fail to see any code, > anywhere, that changes this.currentbuffer to be something > else. Besides, if you''re just using it as a toggler, use an > explicit boolean instead.Yep, spotted that one just after posting too.> > > Effect.FadeOut(visiblebuffer); > > Effect.FadeIn(hiddenbuffer); > > Proper effect usage mandates creating new effects instead of > calling them "statically" like this: > > new Effect.FadeOut(visiblebuffer); > new Effect.FadeIn(hiddenbuffer);Not only that but they should be Effect.Fade and Effect.Appear respectively and I''m not passing the fadetime. That''s cleared up why the fade isn''t working though. Thanks for the advice, what a nice group this is ;) Tim --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
Tim Lockwood
2007-Feb-26 16:40 UTC
Re: Newbie problem, this.options is not defined in member function.
I''ve modified the code considerably since this morning, pretty smooth now in FF... Just one problem now, the fade effect doesn''t work in MSIE (bloody typical). Anyone got any hints? I think this''ll make a nice reusable component for anyone to use, and I''ll be posting it for public consumption when it''s trouble free. Code Follows: /** * Class Effect.SlideShow * * Version: 0.8 * Author: Tim Lockwood <tim-DfnMsfmDEa4g1nBlmp2EgA@public.gmane.org> * * If you find this script useful, please go ahead and use it, pass it around, * tweak it, and generally have a great time with it. * * All I ask is that you leave these headers intact. * * Usage: * * Include scriptaculous & prototype as normal, then this file. Create your static image on * the page with position:absolute and height, width, etc set. * * On the calling page, just create a new Effect.Slideshow on document load and pass an array * of image URLs to it. * * new Effect.SlideShow($(''myimageid''), [''image1.jpg'', ''image2.jpg'', ''image3.jpg'']); * */ // TODO : Fade effect only works in Firefox at the moment, not sure why IE doesn''t like it. Effect.SlideShow = Class.create(); Object.extend(Object.extend(Effect.SlideShow.prototype, Effect.Base.prototype), { // Constructor initialize: function(element) { this.element = $(element); this.options = Object.extend({ slidetime: 6, duration: 3, height: ''200px'', width: ''200px'', top: ''0px'', left: ''0px'', images: new Array() }, arguments[1] || {}); this.frontimage = document.createElement(''div''); this.frontimage.setAttribute(''id'', ''frontimage''); this.backimage = document.createElement(''div''); this.backimage.setAttribute(''id'', ''backimage''); Element.setStyle(this.backimage, { height:Element.getStyle(this.element, ''height''), width:Element.getStyle(this.element, ''width''), top:Element.getStyle(this.element, ''top''), left:Element.getStyle(this.element, ''left''), position:''absolute'', display:''inline-block'' }); Element.setStyle(this.frontimage, { height:Element.getStyle(this.element, ''height''), width:Element.getStyle(this.element, ''width''), top:Element.getStyle(this.element, ''top''), left:Element.getStyle(this.element, ''left''), position:''absolute'', display:''inline-block'' }); this.element.parentNode.appendChild(this.backimage); this.element.parentNode.appendChild(this.frontimage); this.currentbuffer = 0; this.imagecursor = 0; this.pe = new PeriodicalExecuter(this.shownext.bind(this), this.options.slidetime); this.shownext(); }, // Show Next Image shownext: function() { var ef = new Effect.Appear(this.frontimage, { duration:this.options.duration, afterFinish: this.onappearfinish.bind(this) }); }, // Appear effect onfinish callback onappearfinish: function() { this.imagecursor++; if(this.imagecursor == this.options.images.length) { this.imagecursor = 0; } // Copy the frontbuffer to the back buffer Element.setStyle(this.backimage, { background: Element.getStyle(this.frontimage, ''background-image'') }); // Hide the front buffer. Element.setStyle(this.frontimage, { opacity:0 }); // Load the new image into the front buffer ready for the next clock tick. Element.setStyle(this.frontimage, { background:"url(''" + this.options.images[this.imagecursor] + "'') no-repeat"}); } }); --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---