js interpretation fonction eval "style"

js interpretation fonction eval "style" - HTML/CSS - Programmation

Marsh Posté le 22-12-2012 à 11:39:50    

Bonjour, voici le code incomplet d'une de mes fonctions
Je souhaite ici évaluer le paramètre "crea", si ce dernier est une string, afin de pouvoir, par exemple manipuler le style de l'objet, ou faire focus, blur etc..
Cette fonction est appellée derrière une autre ( qui attend que le body soit chargé avant d'essayer d'accéder aux objets ... )

Code :
  1. <div id='div1'>div1 test</div>
  2. <script>function $x(id,crea,html,append){
  3.    x=document.getElementById(id);
  4.    //crea->if(is_string(crea))x.'crea'=html;    //est-ce possible, faut-il que je passe par un éval ???
  5. }
  6. $x('div1','style.background','#FF0000');//Pour utiliser ainsi : mettre le background de la div id=div1 en rouge
  7. </script>


Mon explication est sommaire .. j'espère que vous comprendrez

 

Merci pour vos lumières :jap:


Message édité par grosbin le 22-12-2012 à 11:41:35

---------------
Photos Panoramiques Montagnes Haute Savoie
Reply

Marsh Posté le 22-12-2012 à 11:39:50   

Reply

Marsh Posté le 22-12-2012 à 13:48:05    

Eval, il faut l'éviter !
A part pour la conversion du JSON, et encore... !

 

Tu peux essayer un truc comme ca je pense :

Code :
  1. function $x (id, crea, html, append)
  2. {
  3.   var x = document.getElementById (id); // si tu mets pas 'var', c'est une variable globale que tu créées
  4.   // si le noeud a été trouvé et qu'il s'agit bien d'un element HTML (donc avec les propriétés qu'il te faut)
  5.   if (x && x instanceof HTMLElement)
  6.   {
  7.     // ton code ...
  8.   }
  9.   return false;
  10. }
 

Par contre, ton "x.'crea'=html", ca ne fonctionnera pas !
Tu peux passer dans crea un object, du style { style: 'background-color: red', innerHTML: "blabla.." }
et le traverser avec une boucle du type for ... in
Par exemple

Code :
  1. for (var i in crea) {
  2.   x[i] = crea[i];
  3. }


Message édité par SICKofitALL le 22-12-2012 à 14:04:33

---------------
We deserve everything that's coming...
Reply

Marsh Posté le 22-12-2012 à 14:03:22    

Thanks a lot :jap:


---------------
Photos Panoramiques Montagnes Haute Savoie
Reply

Marsh Posté le 15-01-2013 à 13:11:47    

Fonctionne très bien pour le innerHTML,
Pour le style, s'il est dans la chaine je l'ai mis de la sorte x.style[i]=crea[i] et cela passe
Par contre si je souhaite que le js évalue dynamiquement x.style.qqueschose=argument .. là cela ne passera pas
de plus, puis-je attribuer des évenements du style "x.focus();"


Message édité par grosbin le 15-01-2013 à 15:24:39

---------------
Photos Panoramiques Montagnes Haute Savoie
Reply

Marsh Posté le 17-01-2013 à 19:37:33    

Tu peux mettre ton code qu'on matte ca ?


---------------
We deserve everything that's coming...
Reply

Marsh Posté le 17-01-2013 à 20:29:24    

scuzi

Code :
  1. found=document.getElementById(id);
  2. if(typeof(crea)=='object'){
  3.         for(var i in crea){
  4.           if(i.indexOf('style')>-1){i2=i.replace('style.','').replace('style','');if(i2)found.style[i2]=crea[i];}
  5.           else found[i]=crea[i];
  6.         }
  7. }


Message édité par grosbin le 17-01-2013 à 20:30:11

---------------
Photos Panoramiques Montagnes Haute Savoie
Reply

Marsh Posté le 17-01-2013 à 21:03:40    

ouhla ca m'a l'air bien bordélique tout ca ! Vouloir relire tout ca dans 6 mois et c'est le bug assuré :o
M'enfin bref :)
 
En fait ce que je voulais c'est ton code complet, à savoir la fonction ainsi que la facon dont elle est appellée.


---------------
We deserve everything that's coming...
Reply

Marsh Posté le 17-01-2013 à 21:12:19    

Je la raccourci un peu pour suivre comme il faut

Code :
  1. function $x(id,crea,autresargumentspasinteressantsici){
  2.     found=document.getElementById(id);
  3.     if(typeof(crea)=='object'){
  4.             for(var i in crea){
  5.               if(i.indexOf('style')>-1){i2=i.replace('style.','').replace('style','');if(i2)found.style[i2]=crea[i];}
  6.               else found[i]=crea[i];
  7.             }
  8.     }
  9. elseif(crea==1)null;//on crée l'élement div correspondant
  10. }


---------------
Photos Panoramiques Montagnes Haute Savoie
Reply

Marsh Posté le 18-01-2013 à 00:04:53    

grosbin a écrit :

Je la raccourci un peu pour suivre comme il faut

Code :
  1. function $x(id,crea,autresargumentspasinteressantsici){
  2.     found=document.getElementById(id);
  3.     if(typeof(crea)=='object'){
  4.             for(var i in crea){
  5.               if(i.indexOf('style')>-1){i2=i.replace('style.','').replace('style','');if(i2)found.style[i2]=crea[i];}
  6.               else found[i]=crea[i];
  7.             }
  8.     }
  9. elseif(crea==1)null;//on crée l'élement div correspondant
  10. }


 

Je sais pas si j'ai tout compris à ce que tu veux faire exactement, mais en gros tu veux passer en parametre une série de style, evenements, etc... à un element qui potentiellement n'existe pas ?
En supposant que c'est ce que tu veux faire :

Code :
  1. function $x (id, crea)
  2. {
  3.  // en JS, faire des objets est super simple. Profitons-en en créant une structure du style { style: { /* liste des styles à appliquer */ }, events: { /* liste des events */ }, tag: /* nom du tag en string qui doit etre crée si l'elem n'est pas trouvé */ }
  4.  var i,
  5.   found = document.getElementById (id); // sans le var, ca devient un variable globale, et ce n'est pas ce que tu veux je pense ;)
  6.  if (!found) {
  7.   // si on trouve pas l'elem et que le tag a été fourni, on peut le créer
  8.   if (crea.tag) {
  9.    found = document.createElement (crea.tag);
  10.   }
  11.   else {
  12.    return false;
  13.   }
  14.  }
  15.  // on applique les styles s'ils existent
  16.  if (crea.style)
  17.  {
  18.   for (i in crea.style)
  19.   {
  20.    found.style[i] = crea.style[i];
  21.   }
  22.  }
  23.  // on assigne les eventuels evenements (le 'on' est implicite)
  24.  if (crea.events)
  25.  {
  26.   for (i in crea.events)
  27.   {
  28.    found['on' + i] = crea.events[i];
  29.   }
  30.  }
  31.  // on assigne les eventuelles classes
  32.  if (crea.className) // class est un mot reservé !
  33.  {
  34.   found.className = crea.className.join (' ');
  35.  }
  36.  return found;
  37. }
  38. // exemples d'appel :
  39. // on chope l'elem avec l'id 'unID', on lui applique une liste de styles, un evenement onclick, et 2 classes css
  40. var unIDel = $x ('unID', {
  41.       style:  { backgroundColor: 'red', color: '#FF0' },
  42.       events:  { 'click': function (e) { e = e || window.event; alert ('clicked !' + e.target ); } },
  43.       className: [ 'class1', 'class2' ]
  44.      });
  45. // la même chose mais avec juste une classe
  46. var unIDel = $x ('unID', { className: [ 'classTruc' ] });
  47. // on suppose que 'trucID' n'existe pas, on en fait donc un div par exemple, avec la liste de params qu'on veut
  48. var trucIDel = $x ('trucID', {
  49.       tag:  'div',
  50.       style: { color: 'black' },
  51.       events: {
  52.          'mouseover':function (e) { e = e || window.event; alert ('hovering !'); },
  53.          'mouseout': function (e) { e = e || window.event; alert ('out !'); }
  54.         }
  55.      });
 

j'ai pas testé le code, mais en cas de soucis ou si t'as des questions (ou si j'ai rien compris :D), hésites pas !
Juste pour info, des librairies comme jQuery font ce genre de manips sans aucun soucis ;)


Message édité par SICKofitALL le 18-01-2013 à 10:13:35

---------------
We deserve everything that's coming...
Reply

Marsh Posté le 18-01-2013 à 10:00:41    

Superbe, merci pour ta réponse, en réalité je reprends le développement d'un backoffice gestion des rdv, dans ce dernier je dois mettre à jour dynamiquement des valeurs de champs s'il elles sont modifiées par une personne ( par le biais d'ajax, toutes les 5 secondes )
Le défi pour moi est :  
1) Les champs peuvent ne pas exister, selon la vue, tri et recherches effectuées
2) Il est possible également que le body ou toute la page ne soit pas finie de charger
( la fonction renvoie sur un timeout pour se réexecuter un fois que ce dernier est bien chargé, pour ne pas louper un champ, par exemple )
-- Là je ne suis pas certain que ce soit la meilleure pratique ..
 
3) J'adore cette façon de passer les arguments à l'objet, et me permet notamment, de les faire passer par le timeout
4) effectivement je l'ai nommée pour pouvoir également utiliser le jquery avec :)
 
Merci pour ton aide précieuse


---------------
Photos Panoramiques Montagnes Haute Savoie
Reply

Marsh Posté le 18-01-2013 à 10:00:41   

Reply

Marsh Posté le 18-01-2013 à 10:13:58    

Pas de soucis. Si t'as d'autres questions hésites pas :)


---------------
We deserve everything that's coming...
Reply

Marsh Posté le 18-01-2013 à 10:56:53    

Ca passe nickel, juste parfois j'ai mon console.log qui n'affiche rien ou n'affiche seulement au bout de n secondes .. puis s'est remis à fonctionner comme il faut ..
Pour passer une action, ici found.focus je pense à

Code :
  1. if(crea.func)for(i in crea.func)eval(found.func[i]);



Message édité par grosbin le 18-01-2013 à 12:15:02

---------------
Photos Panoramiques Montagnes Haute Savoie
Reply

Marsh Posté le 18-01-2013 à 12:07:53    

Je vais profiter de ta gracieuse aide et permission :)
Cette fonction me fait poireauter les instructions sur $x() tant que le corps du document n'est pas chargé
( pour éviter de louper un tag by id .. )

Code :
  1. function wait(fun,cond){if(!cond)cond='!$bodyloaded';
  2.   if(eval(cond)){
  3.     if(document.body!=null)$bodyloaded=1;
  4.     else{setTimeout(function(){wait(fun,cond);},200);return;}
  5.   }
  6. //Ici une expression vite faite pour faire passer les quotes, doubles quotes, mais qui du coup m'isole mon objet "crea" entre quotes ..
  7. //du coup cette eval dégueulasse me pourrit un peu les instructions ..
  8.   fun=fun.replace(/^},^{/gi,'","').replace("(",'("').replace(" )",'" )').replace(/\"'/g,"\"" ).replace(/'\"/g,"\"" ).replace(/\"\"/g,"\"" ).replace(/\(\"+\)/g,"()" );
  9.   eval(fun);return;
  10. }


Je précise bien que c'est l'unique solution que j'ai trouvée à ce jour .. faire un while(bodynotloaded) pause et plante le code sur n secondes, pas génial
Je pensais éventuellement peupler une matrice d'instructions, mais repassant également par eval au final .. bref .. pas gégé mon code

 

A moins que je fasse wait("FonctionA()" ) et FonctionA(){$x(id,crea,etc..);} .. on comprend bien que la fonction wait casse un peu tout le trip .. :jap:

 

Afin de mieux comprendre l'idée finale que je souhaite en faire ( messy inside )

Code :
  1. function wait2(fun,cond,a1,a2,a3,a4,a5,a6){et='';//var a=non globale;utiliser this.a pour que ce soit static !
  2.   var args=Array.prototype.slice.call(arguments);args.shift();args.shift();//on dépile les deux premiers éléments
  3.   if(!cond)cond='!$bodyloaded';
  4.   if(eval(cond)){
  5.     if(document.body!=null)$bodyloaded=1;
  6.     else{setTimeout(function(){wait2(fun,cond,a1,a2,a3,a4,a5,a6);},200);return;}//je ne pourrais pas passer les arguments de args à la pelle ?
  7.   }
  8. if(args){fun+='('+args.join(',')+')';}else fun+='()';;
  9.   //if(a1){+a1;if(a2)fun+=','+a2;if(a3)fun+=','+a3;if(a4)fun+=','+a4;if(a5)fun+=','+a5;if(a6)fun+=','+a6;fun+=')';}
  10.   et='w2:'+fun;if($db.indexOf(et)<1){$db+=et;clog(et);}//fonction pour debug
  11.   eval(fun);return;//
  12. }
  13. function $x(id,crea,html,append){
  14.   if(document.body==null){wait2('$x','',id,crea,html,append);return;}

Ce que je souhaite au final dépasser c'est cette erreur quand je transborde un objet .. qui apparement n'est pas transmis de la bonne façon ..
SyntaxError: missing ] after element list : $x(main,[object Object])


Message édité par grosbin le 18-01-2013 à 12:59:22

---------------
Photos Panoramiques Montagnes Haute Savoie
Reply

Marsh Posté le 18-01-2013 à 12:43:45    

le soucis avec les timeout c'est que ca reste aléatoire. Et si le temps que tu as défini n'est pas suffisant ?
Pourquoi ne pas utiliser tout simplement l'evenement window.onload, ou mieux via jQuery la fonction "ready" (check la doc pour ca http://api.jquery.com/ready/ ;)).
 
Sinon saches que les fonction en JS peuvent être invoquée, car ce sont des object comme les autres. Càd que tu définis ta fonction SANS l'executer (càd sans les parentheses à la fin de celle-ci), et que tu la passes en params.
 
Par exemple, pour un setTimeout :

Code :
  1. var maFunc = function () { console.log ('yeah !'); };
  2. setTimeout (maFunc, 1000); // ce qui executera maFunc au bout de 1s


 
Si on partira dans l'idée d'un wait par exemple :

Code :
  1. var maFunc = function () { console.log ('yeah !'); };
  2. var wait = function (callback)
  3. {
  4.   // ... ton code
  5.   callback && callback (); // si callback est défini dans les params, alors on l'execute
  6. }
  7. // et pour appeller ca  :
  8. wait (maFunc);


 
Et de grâce, oublie les eval et penses à mettre des var dans les variables que tu définis au sein de tes fonctions, sinon c'est le bourdel assuré dans le browser ! :)
 
Si tu utilises FireBug, tu peux checker les variables existantes au sein de ton code, et ainsi tracer ce qui est globale (le mal ! :o) et ce qui ne l'est pas (car ca ne doit pas l'être)  ;)


---------------
We deserve everything that's coming...
Reply

Marsh Posté le 18-01-2013 à 13:20:05    

roaaaarr :D Fine :D
exactement j'ai découvert la console js via firebug y'à pas longtemps, cela m'est d'une grande aide :jap:
Mais, du coup, pour passer les paramètres de la function maFunc, spécifiquement pour l'objet crea par exemple, je fais comment ?

 

Dans firebug j'ai compris profilage, mais pas encore trouvé le listing de toutes les globales
de toutes façons si je défini var a; dans une fonction celle dernière ne sera valable que pour une execution
&& this.a définirait une variable statique de la fonction ou globale ?


Message édité par grosbin le 18-01-2013 à 13:35:12

---------------
Photos Panoramiques Montagnes Haute Savoie
Reply

Marsh Posté le 18-01-2013 à 13:40:44    

Je vois ton soucis. Tu peux utiliser ca :

Code :
  1. Function.prototype.attach = function ()
  2. {
  3.  var ptr = this,
  4.   toArray = Array.prototype.slice,
  5.   a = toArray.apply(arguments); // on transforme le pseudo-array arguments en vrai Array
  6.  return function ()
  7.   {
  8.    return ptr.apply (null, a.concat (toArray (arguments)));
  9.   };
  10. };
  11. var maFunc = function (param1, param1) { /*.. code ... */ };
  12. var monCallback = maFunc.attach (vraiParams1, vraiParams2);


Désormais, lorsque tu invoqueras monCallback (càd tu fais

monCallback ()

tel quel ), c'est maFunc que tu appelleras en réalité, mais avec les params vraiParams1 et vraiParams2 qui y seront déjà attachés :)
Toutefois, ca reste dynamique :)


---------------
We deserve everything that's coming...
Reply

Marsh Posté le 18-01-2013 à 13:43:42    

Et pour fireBug, ca se passe dans l'onglet DOM, en décochant "show DOM properties" (ou l'équivalent en FR) pour ne voir que les variables, et pas ce qui est en rapport avec le DOM justement (sauf si t'en as besoin of course).


---------------
We deserve everything that's coming...
Reply

Marsh Posté le 18-01-2013 à 13:52:43    

Je vais finir par devoir te faire un don vu ton aide conséquente :jap:
J'ai également compris que les variables statiques ne sont pas dispos en js, donc utiliser des globales bien nommées :)
En testant

Code :
  1. Function.prototype.attach = function ()
  2. {
  3. var ptr = this,toArray = Array.prototype.slice,a = toArray.apply(arguments); // on transforme le pseudo-array arguments en vrai Array
  4. ===>//a=[5,6] toArray=slice()
  5. return function ()
  6.   {
  7.    return ptr.apply (null, a.concat (toArray (arguments)));
  8.   };
  9. };
  10. var vp1=5;var vp2=6;
  11. var maFunc=function(p1,p2){console.log(p1+','+p2);};
  12. var monCallback=maFunc.attach(vp1,vp2);
  13. monCallback();maFunc(1,2);


J'ai TypeError: can't convert undefined to object : return ptr.apply (null, a.concat (toArray (arguments)));
( même avec jquery chargé )


Message édité par grosbin le 18-01-2013 à 16:58:20

---------------
Photos Panoramiques Montagnes Haute Savoie
Reply

Marsh Posté le 18-01-2013 à 17:02:08    

En bricolant j'ai trouvé ce code convient bien mieux :)

Code :
  1. Function.prototype.attach=function(){
  2. var ptr=this,a=Array.prototype.slice.call(arguments);
  3. return function(){return ptr.apply(null,a);}
  4. }


puis l'interprétation finale dans mon "wait":

Code :
  1. if(!$bodyloaded){x2=$x.attach(id,crea,html,append,noexists);setTimeout('x2()',200);return;}


Donc x2 est une globale, il faudrait que je puisse définir son nom dynamiquement afin d'en lancer plusieurs, distinctes, d'affilées ..

Code :
  1. if(!$bodyloaded){i++;window['f'+i]=$x.attach(id,crea,html,append,noexists);setTimeout('f'+i+'()',200);return;}



Message édité par grosbin le 18-01-2013 à 17:30:54

---------------
Photos Panoramiques Montagnes Haute Savoie
Reply

Marsh Posté le 18-01-2013 à 17:08:06    

oui mon ...toArray.apply (arguments) était foireux, en passant par call ca marche direct, ou alors il aurait fallu faire ...toArray.apply (null, arguments)
 
Je devrais prendre plus le temps de tester le code que je te ponds :D


---------------
We deserve everything that's coming...
Reply

Marsh Posté le 18-01-2013 à 17:31:11    

Je te remercie, tu m'as mis sur le droit chemin, je te dois une chandelle :jap:


---------------
Photos Panoramiques Montagnes Haute Savoie
Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed