2014-05-07 3 views
2

J'ai simple code javascript jquery:Jquery: Utilisez SetInterval lorsque vous cliquez sur

http://jsfiddle.net/reX2N/

Je pensais que ça marcherait, mais ce n'est pas! Je ne reçois aucune erreur ou quoi que ce soit, est-ce que quelqu'un sait pourquoi?

var colors = ['red','green','blue']; 

$('button').on('click',function(){ 
    var index = $(this).parent().index(); 
    setInterval(function(){ 
     $(this).parent().css('background',colors[index]); 
     index < 3 ? index++ : index = 0; 
    }, 1000); 
}); 

code html

<div class="titleBox"> 
     <button>Click meh!</button> 
    </div> 
    <div class="titleBox"> 
     <button>Click meh!</button> 
    </div> 
    <div class="titleBox"> 
     <button>Click meh!</button> 
    </div> 

.titleBox { 
    width:200px; 
    height:200px; 
    float:left; 
    border:1px solid; 
    opacity:.5 
} 
.titleBox[style^="background"] { 
    opacity:1; 
} 
+2

Parce que 'this' est l'étendue de la fenêtre. – epascarello

+0

'this' n'est pas le bouton de la portée setInterval. – Beterraba

Répondre

3

Assigner $(this) en dehors de setTimeout(), puis passer la variable dans la fonction de temporisation par référence:

Example Here

$('button').on('click',function(){ 
    var self = $(this); 
    var index = $(this).parent().index(); 
    setInterval(function(){ 
     self.parent().css('background',colors[index]); 
     index < 3 ? index++ : index = 0; 
    }, 1000); 
}); 
+1

Ce serait bien d'expliquer à l'OP que 'this' devient quelque chose d'autre dans' setInterval', dans ce cas, l'objet global. Une autre façon de le réparer est d'utiliser 'Function.bind' –

+1

@JuanMendes Votre commentaire va l'expliquer. 1+ à votre réponse si. Je ne connaissais pas '.bind'. –

+0

Vous pouvez également simplement passer l'objet 'event' et utiliser' $ (event.currentTarget) '. –

2

Cela permettra de résoudre votre problème , changez votre js en de cette façon:

$('button').on('click',function(){ 
    var index = $(this).parent().index(); 
    var $el = $(this); 
    setInterval(function(){ 
     $el.parent().css('background',colors[index]); 
     index < 3 ? index++ : index = 0; 
    }, 1000); 
}); 
2

Le problème est que l'intérieur de setInterval, this va généralement pointer vers l'objet global (fenêtre), pas l'élément DOM comme dans le gestionnaire de clic. Vous avez deux options:

magasin this comme une variable distincte et l'utiliser de la fonction anonyme setInterval

$('button').on('click',function(){ 
    var self = $(this); 
    var index = $(this).parent().index(); 
    setInterval(function(){ 
     self.parent().css('background',colors[index]); 
     index < 3 ? index++ : index = 0; 
    }, 1000); 
}); 

Bind votre setInterval gestionnaire de sorte que vous ne perdez pas this dans la fonction anonyme

$('button').on('click',function(){ 
    var index = $(this).parent().index(); 
    setInterval(function(){ 
     $(this).parent().css('background',colors[index]); 
     index < 3 ? index++ : index = 0; 
    }.bind(this), 1000); 
}); 
+2

Pour être compatible IE8, une alternative à 'bind()' est le '$ .proxy()' de jQuery ' –

2

Comme alternative, puisque vous avez vos réponses, serait d'utiliser l'objet event passé comme arguments d'un eventHandler (onclick, onchange, ...)

$('button').on('click',function(ev){ 
    var index = $(this).parent().index(); 
    setInterval(function(){ 
     $(ev.currentTarget).parent().css('background',colors[index]); 
     index < 3 ? index++ : index = 0; 
    }, 1000); 
}); 

Maintenant, je remarque que vous répéter des choses, alors vous pouvez peut-être faire comme ceci:

$('button').on('click',function(){ 
    var parent = $(this).parent(), 
     index = parent.index(); 

    setInterval(function(){ 
     parent.css('background',colors[index]); 
     index < 3 ? index += 1 : index = 0; 
    }, 1000); 
}); 
+0

merci. c'est une autre bonne réponse. – user3613548

+0

Cela fonctionnera tant que le bouton n'a aucun élément enfant. Sinon, c'est ce qui serait dans currentTarget lorsqu'on clique dessus –

Questions connexes