Toon posts:

Javascript: Object wordt window object bij setTimeout()v

Pagina: 1
Acties:

Verwijderd

Topicstarter
Oké, ik heb een soort divSlider met ease gemaakt. Als ik maar 1 div wil open en toe klappen mbv deze klasse, geen probleem, dan maakte ik een globale variabele aan die het "object" bevat, maar als ik nou 4 objecten heb kan ik geen gebruik meer maken van m'n globale variabele anders kunnen ze niet allemaal tegelijk open/toeschuiven...

Code:

JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
var globalSlider = "";
var globalSliderBusy = false;

function DivSlider(div, toHeight){
   this.div = document.getElementById(div);
   this.state = true;
   this.active = false;
   this.toHeight = toHeight;
   this.ch = toHeight;
}

DivSlider.prototype.doSlide = function(){
   if (!this.active){
      if (this.state){
//         window.alert(this);
         this.doSlideIn();
      }else{
//         window.alert(this);
         this.doSlideOut();
      }
   }
}

DivSlider.prototype.doSlideOut = function(){
   var obj = this;
   window.alert(obj);
   if ((obj.toHeight - obj.ch) > 1){
      obj.ch += Math.ceil(parseInt(obj.toHeight - obj.ch) / 8);
      obj.div.style.height = obj.ch + "px";
      window.setTimeout(obj.doSlideOut, 15);
   }else{
      obj.div.style.height = obj.toHeight + "px";
      obj.ch = obj.toHeight;
      obj.active = false;
      obj.state = true;
      obj = "";
      objBusy = false;
   }
}

DivSlider.prototype.doSlideIn = function(){
   var obj = this;
   window.alert(obj);
   if (obj.ch > 1){
      obj.ch -= Math.ceil(parseInt(obj.ch) / 8);
      obj.div.style.height = obj.ch + "px";
      window.setTimeout(obj.doSlideIn, 15);
   }else{
      obj.div.style.height = 0 + "px";
      obj.ch = 0;
      obj.active = false;
      obj.state = false;
      obj = "";
      objBusy = false;      
   }
}


'k heb me al suf gegoogled en gedaan, maar ik geraak d'r echt niet uit :s

Tevens heb ik het object al meegegeven als parameter maar dan kregek opnieuw een warrige error dat er een ] ontbrak na m'n object, terwijl ik helemaal geen vierkante haakjes gebruikt heb/had :s

Een werkend voorbeeld ervan kan je hier bekijken:
http://joggink.be/messagepad (hier is d'r maar 1 divSlider object, en dat is de div met het fomulier), deze werkt zonder problemen maar daar gebruik ik m'n globale variabele...

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 09:49

crisp

Devver

Pixelated

Je geeft nu enkel een reference naar een functie, en die wordt logischerwijs in de global scope uitgevoerd. Dit is het beste op te lossen met een closure:
JavaScript:
1
window.setTimeout(function() { obj.doSlideIn(); }, 15);

Intentionally left blank


Verwijderd

Topicstarter
crisp, you're my hero :> (op Scott Schiller na dan)

  • Clay
  • Registratie: Oktober 1999
  • Laatst online: 09-02 10:42

Clay

cookie erbij?

Dit probleem kom je ook vaak tegen bij event handlers. Ipv elke keer de scope via een closure doorgeven kan je ook een helper functie aan Function prototypen die dat voor je doet:

JavaScript:
1
2
3
4
5
6
Function.prototype.delegate = function(scope) {
   var reference = this;
   return function() {
      reference.apply(scope, arguments);
   }
} 


En dan in het geval van de timeout:
JavaScript:
1
this.setTimeout(this.doSlide.delegate(this), 15);


dan heb je die var obj = this; ook niet meer nodig. Mocht je het ranzig vinden dingen aan Function te prototypen kan je de delegate natuurlijk ook als functie van je custom object schrijven. 't lijkt misschien overhead, maar in de praktijk is dit echt een razend handige functie :)

Overigens houd ik er zelf van bij dit soort objecten niet een id, maar gewoon een verwijzing naar een htmlElement mee te geven aan nieuwe object instanties. Dan heb je in je source ook niet de restrictie om voor alles wat animeren moet id's op te gaan geven. Het hoeft ook niet alleen op div's te slaan natuurlijk :P

Instagram | Flickr | "Let my music become battle cries" - Frédéric Chopin


  • crisp
  • Registratie: Februari 2000
  • Laatst online: 09:49

crisp

Devver

Pixelated

Clay: dat is ongeveer wat prototype's bind() ook doet.
Verder eens met het bijhouden van een reference naar je HTMLElement in een property van je object-instance:
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
function MyThingy()
{
    this.x = 0;
    this.el = document.createElement('div');
    this.el.className = 'foo';
    document.body.appendChild(this.el);
}
MyThingy.prototype =
{
    slide: function()
    {
        this.x += 5;
        if (this.x < 400)
        {
            this.el.style.left = this.x + 'px';
            setTimeout(bind(this, this.slide), 20);
        }
    }
}

function bind(el, func)
{
    return function() { func.call(el); }
}

var thing = new MyThingy();
thing.slide();

:)

Intentionally left blank