Précédent   Forum des professionnels en informatique > Webmasters - Développement Web > JavaScript
JavaScript Forum programmation JavaScript. Lire : Cours JavaScript, FAQ JavaScript, Toutes les FAQ JavaScript et Sources JavaScript
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 17/06/2011, 08h19   #1
Futur Membre du Club
 
Damien
Inscription : juillet 2009
Messages : 50
Détails du profil
Informations personnelles :
Nom : Damien

Informations forums :
Inscription : juillet 2009
Messages : 50
Points : 16
Points : 16
Par défaut Référence à un objet

Bonjour à tous !

Pour expliciter le contexte, dans le cadre d'un projet, j'ai pas le droit à jQuery Mais j'ai le droit de plus ou moins le refaire ^^ Je me suis donc lancé dans cette aventure, mais je bloque sur un soucis de "context" je dirais...

Sur le code qui va suivre, tout fonctionne presque Seul soucis : en cas de fonctions avec timer (animation, par exemple), si deux animation se croise, l'objet courant dans l'animation est le dernier appelé. Forcément, pour faire un callback, ça le fait pas du tout...

Pour le moment, $('element') ne récupère qu'un élément HTML d'ID "element". Ce sera améliorer par la suite, quand j'aurais résolu ce problème de "this"..

Voilà le code ^^

Code :
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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
<script type="text/javascript">
(function(){
		jWibi = window.$ = function(selector, context) {
			return jWibi.init(selector, context);
		};
		jWibi = jWibi.prototype = {
			version: '1.0',
			selector: null,
			init: function(selector){
				selector = selector || document;
				if(typeof selector === 'string'){
					this.selector = document.getElementById(selector);
				}
				return this;
			},
			get: function () { return this.selector; },
			html: function(str){
				if(str){
					this.selector.innerHTML = str;
					return this;
				}else return this.selector.innerHTML;
			},
			css: function(s, v){
				if(s != null && v != null && typeof s === 'string' && typeof v === 'string'){
					this.selector.style[s] = v;
				}else if(s != null && typeof s === 'object'){
					var nb = arguments.length;
					if(nb > 1) for(a in s) this.selector.style[a] = s[a];
					else{
						for(i=1;i<=nb;i++){
							for(a in s) this.selector.style[a] = s[a];
						}
					}
				}
				return this;
			},
			ready: function (func) {
				if (typeof window.onload != 'function') { window.onload = func; }
				else { window.onload = function() { window.onload(); func(); } }
				return window;
			},
			click: function (func) {
				if (typeof this.selector.onclick != 'function') { this.selector.onclick = func; }
				else { this.selector.onclick = function() { this.selector.onclick(); func(); } }
				return this;
			},
			toggle: function() {
				this.selector.style.display = (this.selector.style.display === 'none' || '') ? 'block' : 'none';
				return this;
			},
			opacity: function(level) {
				if(level>=0 && level<=100) {
					this.selector.style.opacity = (level/100);
					this.selector.style.filter = 'alpha(opacity='+level+')';
				}
			},
			fadeOut: function(time) {
				var level = 100;
				var iout = setInterval(function(){
					$(this.selector).opacity(level--);
					if(level==0){ clearInterval(iout); }
				},time/100);
				return this;
			},
			fadeIn: function(time) {
				level = 0;
				var iin = setInterval(function(){
					$(this.selector).opacity(level++);
					if(level==100){ clearInterval(iin); }
				},time/100);
				return this;
			},
			timers: new Array(),
			launchAnim: function(obj, elt, i, currentValue, finishValue, pas, plus, moins, timeRefresh, callback){
				currentValue += pas;
				var objthis = obj;
				ecart = parseFloat(finishValue - currentValue);
				if(plus && ecart > 0 || moins && ecart < 0){
					elt.style[i] = currentValue;
					setTimeout(function(){$().launchAnim(obj, elt, i, currentValue, finishValue, pas, plus, moins, timeRefresh, callback)}, timeRefresh);
				}else{
					currentValue = finishValue;
					elt.style[i] = currentValue;
					var testouille1 = elt.getAttribute("id");
					var testouille2 = obj.selector.getAttribute("id");
					console.log('elt : '+testouille1+', obj: '+testouille2);
					//callback.call(obj);
				}
				return this;
			},
			animate: function(anim, time, callb){
				var animation = anim;
				var duration = time;
				var callback = callb || function(){return;};
				var timeRefresh = 20;
				var nbRefresh = parseFloat(duration / timeRefresh);
				for(var i in animation){
					var currentValue = parseFloat(this.selector.style[i]);
					var finishValue = parseFloat(animation[i]);
					var ecart = parseFloat(finishValue - currentValue);
					if(ecart < 0){var plus = false;var moins = true;}
					else if(ecart > 0){var plus = true;var moins = false;}
					else return this;
					var pas =  parseFloat(ecart / nbRefresh);
					var obj = this;
					var Class = $(this);
					var num = this.timers.length;
					this.timers[num] = obj;
					this.launchAnim(Class, obj.selector, i, currentValue, finishValue, pas, plus, moins, timeRefresh, callback);
				}
				return this;
			}, 
			callbacker: function (func) {
				if (typeof this.selector.callback != 'function') { this.selector.callback = func; }
				else { this.selector.callback = function() { this.selector.callback(); func(); } }
				return this;
			}
		}
})();
</script>
Et pour le test :

Code :
1
2
3
4
5
6
7
8
<script type="text/javascript">
$().ready(function () {
  $('test').animate({'height':'150px'}, 1000, function(){$(this).css('background','#f00')});
  $('test2').animate({'height':'20px'}, 2000, function(){$(this).css('background','#f55')});
});
</script>
<div id="test">test</div>
<div id="test2">test 2</div>
Dans la fonction "launchAnim", le console.log() devrai ressortir :
Citation:
elt : test, obj: test
elt : test2, obj: test2
Mais il ressort :
Citation:
elt : test, obj: test2
elt : test2, obj: test2
J'ai un peu tout essayé, tout bidouiller, j'ai meme mis les "this" à l'appel en array mais malgré ça, ils sont tous remplacé par le dernier appelé, même dans l'array..

Quelqu'un voit peut-être d'où vient le soucis ?
J'ai bien la notion de "contexte" dans mon "init", mais je n'ai pas compris comment l'utiliser, peut être pourrait-il m'aider.. Certainement même.

Merci d'avance à ceux qui liront
WibiMaster est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/06/2011, 08h24   #2
Responsable JavaScript & AJAX

 
Avatar de vermine
 
Inscription : mars 2008
Messages : 2 686
Détails du profil
Informations personnelles :
Âge : 27

Informations forums :
Inscription : mars 2008
Messages : 2 686
Points : 5 756
Points : 5 756
Bonjour,

A quoi vous sert cette instruction ?

__________________
Elen Poukram - Isegoria - Sandawe
vermine est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/06/2011, 08h25   #3
Futur Membre du Club
 
Damien
Inscription : juillet 2009
Messages : 50
Détails du profil
Informations personnelles :
Nom : Damien

Informations forums :
Inscription : juillet 2009
Messages : 50
Points : 16
Points : 16
Citation:
Envoyé par vermine Voir le message
Bonjour,

A quoi vous sert cette instruction ?

À rien, elle était là quand je voulais essayer de conserver localement l'objet instancié..
[EDIT] pas l'objet instancié directement, mais celui passé en paramètre. 'fin dans tous les cas, ça marchait pas. On sent le désespoir de cause dans mon code, désolé
WibiMaster est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/06/2011, 08h36   #4
Responsable JavaScript & AJAX

 
Avatar de vermine
 
Inscription : mars 2008
Messages : 2 686
Détails du profil
Informations personnelles :
Âge : 27

Informations forums :
Inscription : mars 2008
Messages : 2 686
Points : 5 756
Points : 5 756
Par défaut Fourberie !

obj.selector est en fait var obj = this;. Ca porte à confusion car ce qui bloque c'est var Class = $(this); qui devient obj.selector.

Changez le nom de votre variable "Class". C'est pas top d'utiliser un nom réservé (j'hésite à cause de la majuscule).
__________________
Elen Poukram - Isegoria - Sandawe
vermine est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/06/2011, 08h41   #5
Futur Membre du Club
 
Damien
Inscription : juillet 2009
Messages : 50
Détails du profil
Informations personnelles :
Nom : Damien

Informations forums :
Inscription : juillet 2009
Messages : 50
Points : 16
Points : 16
Citation:
Envoyé par vermine Voir le message
obj.selector est en fait var obj = this;. Ca porte à confusion car ce qui bloque c'est var Class = $(this); qui devient obj.selector.

Changez le nom de votre variable "Class". C'est pas top d'utiliser un nom réservé (j'hésite à cause de la majuscule).
Voui je peux changer le terme "Class", je l'ai mis suite à une probable solution trouvé sur un forum.
Du coup euh.. C'était quoi la solution ? ^^

De base, personnellement j'avais juste mis :
Code :
this.launchAnim(this, this.selector, i, currentValue, finishValue, pas, plus, moins, timeRefresh, callback);
Dans launchAnim, this.selector (elt) était bon dans le console.log(), mais this (obj) ne l'était pas, et ne se rapportait qu'au dernier objet instancié..

[EDIT] Euh sinon, this != this.selector ; en faisant $(elt), ça retourne l'objet, le selector est ensuite à l'intérieur de cet objet

[EDIT] Arf okay viens de voir, normalement c'est pas Class qui est passé en parametre mais obj. Ca fait parti de toutes mes manipulations pour essayer de cerner le problème..
WibiMaster est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/06/2011, 10h04   #6
Futur Membre du Club
 
Damien
Inscription : juillet 2009
Messages : 50
Détails du profil
Informations personnelles :
Nom : Damien

Informations forums :
Inscription : juillet 2009
Messages : 50
Points : 16
Points : 16
Par défaut Site de test

En fait après encore moults tests, j'ai l'impression qu'on ne peut pas stocker "this" en variable..
Si je fais un array, tab[], et qu'à chaque nouvelle instance j'enregistre
Eh bien en bouclant sur tab, je me rend compte que tous les this sont identiques, sont tous comme "écrasé" par le dernier.
Dingue.

En guise d'exemple, voilà une page qui cible le problème, le code est raccourcis à l’extrême : http://www.wibimaster.com/findError/
Dans la console, 4 lignes s'afficheront,le problème se distingue à la 3e..
WibiMaster est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/06/2011, 11h26   #7
Responsable Développement Web

 
Avatar de Bovino
 
Homme Didier Mouronval
Développeur Web
Inscription : juin 2008
Messages : 13 807
Détails du profil
Informations personnelles :
Nom : Homme Didier Mouronval
Âge : 41
Localisation : France, Gironde (Aquitaine)

Informations professionnelles :
Activité : Développeur Web
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : juin 2008
Messages : 13 807
Points : 35 803
Points : 35 803
Là il s'agit d'une affectation type PHP, mais ce n'est pas valable en JavaScript.
__________________
Pas de question technique par MP !
Tout le monde peut participer à developpez.com, vous avez une idée, contactez-moi !
Vous possédez un blog et aimeriez diffuser vos billets sur le forum, contactez-moi !
Mes formations video2brain : La formation complète sur JavaScriptJavaScript et le DOM par la pratiquePHP 5 et MySQL : les fondamentaux
Mon livre sur jQuery
Bovino est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/06/2011, 11h36   #8
Futur Membre du Club
 
Damien
Inscription : juillet 2009
Messages : 50
Détails du profil
Informations personnelles :
Nom : Damien

Informations forums :
Inscription : juillet 2009
Messages : 50
Points : 16
Points : 16
Yep, j'ai écrit ça à la va-vite pour le forum, mais dans tous les cas ça ne marche pas.. Il faut regarder la page test, et la source qui est beaucoup plus concise montre directement le soucis. Pour ne pas dénaturer le post, je n'ai pas éditer le 1er message, donc je vais mettre la source ici :

Code :
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
(function(){
	jWibi = window.$ = function(selector, context) {
		return jWibi.init(selector, context);
	};
	jWibi = jWibi.prototype = {
		version: '1.0',
		selector: null,
		init: function(selector){
			selector = selector || document;
			if(typeof selector === 'string'){
				this.selector = document.getElementById(selector);
			}
			return this;
		},
		ready: function (func) {
			if (typeof window.onload != 'function') { window.onload = func; }
			else { window.onload = function() { window.onload(); func(); } }
			return window;
		},
		launchAnim: function(obj, elt, i){
			if(i == 0)
				console.log('Premier passage :: Objet.selector (ID) = '+obj.selector.getAttribute('id')+', Element (ID) = '+elt.getAttribute('id'));
			else
				console.log('Timeout :: Objet.selector (ID) = '+obj.selector.getAttribute('id')+', Element (ID) = '+elt.getAttribute('id'));
			i++;
			if(i < 2) setTimeout(function(){$().launchAnim(obj, elt, i)}, 500);
		},
		animate: function(){
			this.launchAnim(this, this.selector, 0);
			return this;
		}
	}
})();
$().ready(function () {
	$('test').animate();
	$('test2').animate();
});
Avec code comme HTML :

Code :
1
2
<div id="test" style="height: 20px;background: #f00">test</div>
<div id="test2" style="height: 200px;background: #ff0">test2</div>
Et les logs de console à l'exécution :

Citation:
Premier passage :: Objet.selector (ID) = test, Element (ID) = test
Premier passage :: Objet.selector (ID) = test2, Element (ID) = test2
Timeout :: Objet.selector (ID) = test2, Element (ID) = test
Timeout :: Objet.selector (ID) = test2, Element (ID) = test2
On voit à la 3e ligne que l'objet n'est plus le bon..
WibiMaster est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/06/2011, 08h19   #9
Futur Membre du Club
 
Damien
Inscription : juillet 2009
Messages : 50
Détails du profil
Informations personnelles :
Nom : Damien

Informations forums :
Inscription : juillet 2009
Messages : 50
Points : 16
Points : 16
Par défaut Solution

Bien, après avoir écumé d'autres forum, j'ai finit par trouver deux solutions à ce problème. Je post ici la réponse la plus simple, sait-on jamais que quelqu'un en ait besoin, et puis histoire de le marquer comme résolu...

Code salvateur :

Code :
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
(function(){
	jWibi = window.$ = function(selector, context) {
		// Si jWibi est appelé directement, on le rappelle avec new
		// Création d'une instance, donc.
		if(!(this instanceof jWibi)) return new jWibi(selector, context);
		selector = selector || document;
		if(typeof selector === 'string'){
			this.selector = document.getElementById(selector);
		}
		return this;
		// Ici on est sûr d'avoir une instance.
	};
	jWibi.prototype = {
		version: '1.0',
		selector: null,
		ready: function (func) {
			if (typeof window.onload != 'function') { window.onload = func; }
			else { window.onload = function() { window.onload(); func(); } }
			return window;
		},
		launchAnim: function(obj, elt, i){
			if(i == 0)
				console.log('Premier passage :: Objet.selector (ID) = '+obj.selector.getAttribute('id')+', Element (ID) = '+elt.getAttribute('id'));
			else
				console.log('Timeout :: Objet.selector (ID) = '+obj.selector.getAttribute('id')+', Element (ID) = '+elt.getAttribute('id'));
			i++;
			if(i < 2) setTimeout(function(){$().launchAnim(obj, elt, i)}, 500);
		},
		animate: function(){
			this.launchAnim(this, this.selector, 0);
			return this;
		}
	}
})();
Pour le moment pas vu de problème avec ça, ça m'a l'air parfait
WibiMaster est déconnecté   Envoyer un message privé Réponse avec citation 10
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 19h23.


 
 
 
 
Partenaires

Hébergement Web