javascript eval global

Posté le dimanche 1 octobre 2006 à 12 h 33, Read it in english with Google

ça fait un peu prĂšs 1 mois que je cherche Ă  exĂ©cuter mon code javascript contenu dans mes donnĂ©es chargĂ©es via AJAX. Tout le monde me dira qu’il existe eval, seulement voila, ceci ne marche uniquement pour le code Ă©xĂ©cutĂ© en live et non pour les dĂ©claration de fonction.

En effet, mĂȘme dans le framework du style prototype, eval() est dĂ©clarĂ© dans le contexte de l’objet AJAX, autrement dit dans la fonction AJAX. Ainsi toute les fonctions dĂ©clarĂ©es dans eval ne sont disponibles que dans la fonction oĂč l’on fait le eval().

un petit exemple pour m’expliquer :

function myeval(){
  eval('function test(){alert('test ok');}');
  alert(typeof(test)); //affiche function
  test(); // affiche 'test ok'
}
myeval();
alert(typeof(test)); //affiche undefined
test(); // erreur : fonction test inconnu

ceci peut poser de gros problÚmes pour déclarer des objects via AJAX :

//x est votre object XMLHttpRequest
x.onreadystatechange = function (){
  if (this.readyState == 4 && this.status == 200){
    var c = document.getElementById('monconteneur');
    c.innerHTML = x.responseText;
    //maintenant que les donnĂ©es reçu on Ă©tĂ© placĂ© dans la page,
    //il faut exĂ©cuter toutes les balise script :
    var allscript = c.getElementsByTagName('script');
    for(var i=0;i< allscript.length;i++){
      eval(allscript[i].text);
    }
    alert(typeof(une_function_dans_mes_balise_script));//return function
  }
}

seulement voilĂ  : si maintenant vous avez un bouton avec dans l’action onClick une fonction qui est dĂ©clarĂ© dans la page chargĂ©, celle ci ne s’Ă©xĂ©cutera pas car elle n’est pas dĂ©clarĂ© dans un contexte global mais seulement dans la fonction onreadystatechange.

Mais, pour toi public, j’ai la solution. vous pouvez utiliser :

window.eval();
//ou encore :
var global = this; //dans un contexte global
//puis
global.eval();

vos function seront alors déclarée dans un contexte global.
var global = this; est utilisé pour forcé la compatibilité.

A notĂ© que les diffĂ©rents framework tel que prototype n’exĂ©cute pas vos script via eval dans un contexte global (voir la function evalScripts pour prototype).

Je ne vous cache pas que j’ai galĂ©rĂ© pour un truc tout con cependant astucieux 🙂

35 réponses à “javascript eval global”

  1. Skan

    Je crois avoir le mĂȘme problĂšme avec Firefox et les feuilles XSL (pas testĂ© sur IE) mais ça passe sur Safari, et p’tre encore aussi le mĂȘme problĂšme lors d’inclusion de multiples SVG


    Aurais-tu un exemple de code?
    Ton window.eval() tu le mets dans la page « racine » ou dans chaque module chargé?

    Merci 🙂

  2. XoraX

    euh.. qu’est-ce que t’entend par « dans chaque modules chargé » ?
    le window.eval() tu peu le mettre oĂč tu veux tant que t’es sur qu’il va s’exĂ©cutĂ©r.

    dans l’exemple du dessus je mettrais :
    window.eval(allscript[i].text);
    au lieu de :
    eval(allscript[i].text);

    si ça passe pas, tu mets var global = this; Ă  la racine de chez racine puis t’utilise global.eval(); dans tes fonctions.

  3. Skan

    Merci ^^

    Mais en fait c’est pas ça :/

    Firefox 2: les javascripts dans les feuilles XSL importĂ©es ne sont pas exĂ©cutĂ©s. MĂȘme un alert(‘toto’) ne donne rien. Par contre les Javascripts de la feuille XSL initiate fonctionnent bien.

    Safari 2 (+Webkit): un Ă©lĂ©ment SVG dĂ©clarĂ© dans un fichier SVG () est considĂ©rĂ© comme un bloc. J’aurais mis ça aurait Ă©tĂ© pareil. Les Ă©vĂ©nements de clic sont envoyĂ©s Ă  et non sur le nƓud id=3 si j’avais cliquĂ© dessus. C’est un peu comme mettre un gif transparent au-dessus d’une page web, on ne peut alors plus cliquer sur les liens :/
    Et Ă©videmment c’est p’tre pas correcte de rĂ©utiliser la balise SVG Ă  l’intĂ©rieur d’elle-mĂȘme :p

    Je sens que je vais aller poser ma question sur svgfr.org car en gros j’ai un fichier XML gĂ©nĂ©rĂ© dynamiquement. Celui-ci appelle une feuille de transformation XSL. Et quand je reconnais dans mon fichier XML la balise (par exemple), alors j’appelle un template importĂ© de la feuille XSL qui me gĂ©nĂšre mes curseurs (de mĂȘme pour des molettes, des joysticks
)

    Et donc, je cherche une balise SVG qui me permette de définir des nouveaux repÚres histoire de pouvoir faire un zoom sur mon espace de travail sans grossir le HUD, bref plein de choses ^^

  4. Skan

    Tout simplement ^^
    Heureusement « transform » n’agit pas comme « style »: un « style » parent est prioritaire sur les « style » de ses nƓuds enfants. « transform » s’applique en plus.

  5. Alex

    Merveilleux!

    C’est exactement sur quoi j’ai gossĂ© toute la soirĂ©e, exceptĂ© que moi c’est avec un IFRAME crĂ©Ă© dynamiquement.

    Bref, merci d’avoir postĂ© ceci 😉

  6. guillaume

    Merci,

    je galere depuis 2 jours la dessus, et grace a toi tout fonctionne !

    by

  7. XoraX

    de rien 😉 merci d’ĂȘtre passĂ©!
    ++

  8. Cyrille

    Superbe script j’ai jusqu’ici contournĂ© l’utilisation du javascript sur des fichiers chargĂ©s au dĂ©triment de l’ergonomie… Et maintenant, c’est la grande classe. Merci pour ton post, trĂšs pratique, j’ai eu du mal Ă  trouver un script fonctionnel ! ++

  9. XoraX

    Merci! moi aussi je t’explique pas comment j’ai rouillĂ© pour trouver ça d’ailleur je l’ai vu sur un site chinois ou japonais je sais pas j’ai pas pu lire la page juste le bout de code 😀 ++

  10. Belette

    Tout simplement royal!!!
    Comme quoi des fois ca vaut la peine de se creuser les neurones…

  11. Belette

    Dans le mĂȘme esprit, existe t’il une autre solution miracle pour que les appels de scripts externe depuis des page ouvertes en ajax, genre :

    soient également traités dans un contexte global?

  12. Belette

    dĂ©solĂ© les balises n’ont pas Ă©tĂ© prises en compte… il fallait lire :
    script type= »text/javascript » src= »./includes/FCKEditor/fckeditor.js »

  13. XoraX

    et oui ça prend pas le fichier mais tu oeu te débrouiller :

    for(var i=0;i< allscript.length;i++){ if(allscript[i].src){ //et la tu fais un new XHR en l'obligeant Ă  faire un window.eval() sur le responseText } else { window.eval(allscript[i].text); } } cela dit aprĂšs il va falloir que tu gĂšre un certain systĂšme de cache afin d'Ă©vitĂ© de recharger 2 fois le mĂȘme fichier et de redĂ©clarer tes fonctions et autre. Donc met un tableau quelque part oĂč tu va stockĂ© tout les noms des fichiers script dĂ©jĂ  tĂ©lĂ©charger. Je sens que je vais faire un add-on Ă  prototype 🙂

  14. belette

    Effectivement ca marche du feu de dieu, merci Xorax!
    Pour l’histoire d’un systĂšme de cache je me demande si ce ne serait pas plus simple de controler dans les fichiers js inclus de la sorte, si l’une des fonctions ou variables dĂ©clarĂ©es existe dĂ©ja dans le contexte global, et si c’est le cas, de ne pas traiter le fichier.
    Je teste ca, et je donnerais le rĂ©sultat…

  15. Juju

    Merci beaucoup, je commencais a desesperer Ă  trouver la soluce.

  16. Juju

    Bonjour,
    j’ai trouver bien utile ton bout de code, mais j’ai un souci sous IE
    En fait lors de certaines rĂ©ponse j’ai dans mon contenu une redirection du type parent.window.location, que je recupere bien, mais une fois que je modifie mon div, il n’est jamais interprĂ©ter, et quand je vais revĂ©rifier son contenu, en effet le contenu est vide

    voici mon bout de code, quand j’ai la rĂ©ponse ajax
    var global = http_request;
    var c = document.getElementById(‘contenu’);
    c.innerHTML = http_request.responseText;
    //maintenant que les données reçu on été placé dans la page,
    //il faut exécuter toutes les balise script :
    var allscript = c.getElementsByTagName(‘script’);
    for(var i=0;i

  17. XoraX

    humm… je vois pas bien ce qui marche pas. y me faut plus de code!

    si tu cherche Ă  modifier le contenu dans ta parent.window, il faudra faire un parent.window.document.getElementById(’contenu’); en espĂ©rant que ça passe au niveau sĂ©curitĂ©…

  18. XoraX

    allez ça y est mon add-on protoype est pret !! 😀

    il va permettre de faire un global.eval sur les codes inclus dans les balises script mais pas seulement !!
    il va Ă©galement allez rechercher tout les fichiers script inclus du style
    script src=\ »monjs.js\ »
    et tout ça via ajax bien sur 😉

    je le mettrais la semaine prochaine en ligne pour l\’instant dodo 🙂

    ps: ouĂš je sais wordpress c\’est de la merde pour les commentaires pas moyen d\’Ă©clire ce qu\’on veut sans qu\’il vire des trucs se bouffon… mais j\’ai pas envie de plonger le nez dans la bouzzz

  19. Julien

    Recoucou
    je revient vers ce site pour soumettre un probleme
    en fait ma réponse ajax me renvoit des déclarations de variables de type :
    var infoEE84 = [‘UIOM DE DOUCHY’, », »,’59282′,’Douchy-les-Mines’, »,'(UIOM) UnitĂ© d\’incinĂ©ration des ordures mĂ©nagĂšres’,’UIOM DE DOUCHY’];var infoEE85 = [‘UIOM DE MAUBEUGE’, », »,’59600′,’Maubeuge’, »,'(UIOM) UnitĂ© d\’incinĂ©ration des ordures mĂ©nagĂšres’,’UIOM DE MAUBEUGE’];

    et du code HTML exploitant ces données (toutes les fonctions étant déclarées avant)
    mais en fait il est impossible d’utiliser ces donnĂ©es
    je comprend pas pourquoi, si vous avez déja rencontré ce souci postez je reviendrai
    Merci par avance

  20. XoraX

    humm il faudrait des précisions.

    tu dois faire window.eval sur tes donnĂ©es avant d’afficher le code html.
    ton code javascript (inclue dans les balise script) dans ton code html chargé via ajax ne peut pas écrire directement afin de retourné un code html différent.
    Il peut y avoir uniquement des apel de fonction dans des événement du genre onclick= »mafonction(); »

    il faudrait plus de code pour que je puisse t’aider.

  21. Julien

    Merci de ton aide
    Le problĂšme c’est que je peut pas faire un window.eval sur ma rĂ©ponse Ajax car j’ai du javascript et du html.
    Cependant j’ai vĂ©rifier via firefox et « afficher le code source de la sĂ©lection » que j’ai bien mes variables qui sont dĂ©clarĂ©es
    Mais impossible de les utiliser
    un peu plus de code :
    resultat = http_request.responseText;
    setBlocSINOE(infoCorrespondance,resultat);

    var setBlocSINOE = function(divContent, HTML) {

    document.getElementById(‘infoCorrespondance’).innerHTML = HTML;

    }

  22. XoraX

    ok 🙂
    dĂ©solĂ© mais tu va ĂȘtre obligĂ© de faire un window.eval, je ne sais pas ce que te dit firefox mais c’est sur que tes variable ne sont pas dĂ©clarĂ©.
    c’est pas grave si ta du javascript et du html, pour remprendre ton code :

    resultat = http_request.responseText;
    setBlocSINOE(infoCorrespondance,resultat);

    var setBlocSINOE = function(divContent, HTML) {

    var e = document.getElementById(’infoCorrespondance’);
    e.innerHTML = HTML;

    var allscript = e.getElementsByTagName(‘script’);

    for(var i=0;i< allscript.length;i++){ eval(allscript[i].text); } }

  23. Julien

    Merci pour ton aide vraiment
    Mais malheureusement ca ne marche pas
    Je vais devoir trouver une autre technique, en effet je ne passe meme pas dans le for
    Le pire dans tout cas, c’est que je suis sur que je recupere bien ce code javascript.
    Enfin bon du coup j’ai charger mes 1000 lignes de rĂ©sultat possible dans ma page d’appel
    C’est nul je sais mais ca marche en attendant de trouver la solution

    Et encore merci pour ton aide

  24. belette

    Salut,
    J’ai Ă©galement un problĂšme avec IE et les chargement de pages AJAX :
    Sur une inclusion d’un fichier .js dans une page chargĂ© en AJAX, le global.eval(obj.responseText); (le responseText Ă©tant le contenu de mon fichier .js inclus) ne semble pas traiter le code qui n’est pas inclus dans des fonctions.
    Par exemple une simple variable « var toto=1 » n’est pas dĂ©clarĂ©, une fonction alert(« toto »); n’est pas traitĂ©.
    Par contre toutes les autres fonctions dĂ©clarĂ©es dans le fichier .js sont bien traitĂ©es dans le contexte global….
    Aurais tu une idée du problÚme?

  25. belette

    re,
    j’amĂšne un peu plus de prĂ©cision sur le problĂšme citĂ© sur mon post prĂ©cĂ©dent.
    En fait cela fonctionne bien également pour les appels de fonctions. Le problÚme porte en fait uniquement sur les déclarations de variables globales et pas seulement dans des fichiers .js inclus mais aussi dans une page chargé en Ajax.
    Exemple :
    echo  » var titi=’my name is titi’; alert(titi); « ;
    echo ‘afficher titi‘;
    le premier alert(titi) fonctionne, preuve que la premiÚre ligne à bien été traitée par le chargement Ajax.
    En revanche lors d’un appel a titi en dehors de la premiĂšre sĂ©quence de script, IE renvoie l’erreur : ‘titi est indĂ©fini’
    IE gĂšrerait il les variables ou le contexte global d’une maniĂšres diffĂ©rentes? s’agit il ici d’une sĂ©curitĂ© de sa part?
    Pour info la version de IE utilisĂ© est la 6.0 (le 7 plante lamentablement sur mon pc, je n’ai pas pu encore le tester…)

  26. belette

    Il fallait lire :
    echo  » script var titi=’my name is titi’; alert(titi); /script « ;
    echo ‘ a href= »# » onClick= »alert(titi); » afficher titi /a ‘;

  27. XoraX

    bon apparement IE 6 c’est de la belle daube… mais ça c’est pas nouveau 🙂

    en gros il gÚre mal les déclaration de variable avec « var » devant. pour reprendre ton exemple il faudrais faire :

    echo ” script titi=’my name is titi’; alert(titi); /script “;
    echo ‘ a href=”#” onClick=”alert(titi);” afficher titi /a ‘;

    bref on est contraint de ne pas respecter le W3C. Heureusement, une dĂ©claration comme ça ne pose pas de problĂšme sur les autres navigateurs qui sont beaucoup plus indulgent voir mĂȘme intelligent.

    Merci d’avoir fais remarquĂ© ça je crois que j’aurais eu des problĂšme par la suite…

  28. belette

    Salut,
    Je viens de faire quelques tests de compatibilités avec quelques navigo.
    Il semblerait qu’OpĂ©ra n’aime pas trop les :

    document.getElementById(div_to_load).innerHTML=obj.responseText;
    y_exec_scripts(document.getElementById(div_to_load));

    (y_exec_scripts Ă©tant la fonction d’Ă©xec du js.)

    En revanche, il semble bien apprécier :

    document.getElementById(div_to_load).innerHTML= »;
    var ndiv = document.createElement(‘div’);
    ndiv.innerHTML=obj.responseText;
    document.getElementById(div_to_load).appendChild(ndiv);

    A priori les navigateurs, Ă©xĂ©cute par eux meme le js du innerHTML lors de l’appendChild, c’est assez Ă©tonnant… Firefox le fait trĂ©s bien, IE un peu moins… donc pour OpĂ©ra pas besoin a priori d’Ă©valuer le js par la suite.
    En ce qui concerne netscape, la premiĂšre mĂ©thode de xorax fonctionne bien, mais j’ai constatĂ© un bug bizzare dĂ©formant les pages si on a des inclusions de fichiers js en milieu de page, en la mettant Ă  la fin du code, le problĂšme disparait…

    Je continue de tester cela et vous tiens informer

  29. ZeLegolas

    En remplacant :

    function myeval(){
    eval(‘function test(){alert(’test ok‘);}’);
    alert(typeof(test)); //affiche function
    test(); // affiche ‘test ok’
    }

    par

    myeval = function(){
    eval(‘function test(){alert(’test ok‘);}’);
    alert(typeof(test)); //affiche function
    test(); // affiche ‘test ok’
    }

    ca a marche pour moi

  30. kankrelune

    Moi je fais lĂ©gĂšrement diffĂ©rament… je dĂ©clare mes fonctions dans un fichiers js ce dernier Ă©tant inclu dans le code html renvoyĂ© par le raquette XMLHttpRequest… ensuite il me suffit de faire… .. .

    var includedModulesJs = new Array;

    function includeJs(src)
    {  
      if(!includedModulesJs[src])
      {
        var s = document.createElement("script");
        s.src = src;
        head = document.getElementsByTagName('head')[0];
        head.appendChild(s);
        includedModulesJs[src] = true;
      }
    }

    function setInnerContents(targetObj, contents)
    {
      targetObj.innerHTML = contents;

      var allJs = targetObj.getElementsByTagName(”script”);

      for(var i=0; i < allJs.length; i++)
      {
        if(allJs[i].src && allJs[i].src != “”)
        includeJs(allJs[i].src);
        else
        window.eval(allJs[i].innerHTML);
      }
    }

    ensuite il suffit de faire par exemple


    setInnerContents(document.getElementById(”maDiv”), ajaxObject.responseText);

    ;o)

    @ tchaOo°

  31. javascript eval global : part 2 contient sur le sujet :

    […] AprĂšs une premiĂšre approche non sans faille de l’Ă©valuation d’un code javascript dans un contexte global , voici la seconde version, compatible FireFox et IE et tout les navigateurs dĂ©rivĂ©s. Code (javascript) […]

    le mardi 27 février 2007 @ 13 h 04
  32. XoraX

    bonne méthode au fait kankrelune
    j’avais testĂ© une fois mais j’avais surement du faire une erreur parce que ça foirait 🙂
    thanks!

  33. javascript eval global final contient sur le sujet :

    […] Historique : eval global partie 2, eval global […]

    le mercredi 11 avril 2007 @ 17 h 16
  34. Fred

    Hello Ă  tous
    je pose un probleme qui je ne vais pas encore croisé par la.
    Je veux utiliser un effet drag and drop dans mes fichiers retournées par ajax.
    J’utilise une application qui doit executer du cide javascript au retour des donnĂ©es envoyĂ©es par ajax. La mĂ©thode Xorax est niquel mais un probleme e pose lors de l’ajout au window.OnLoad .
    En gros les fonctions window.onload = function (){ ….. } ne s’executent pas …..

    Un petit peu d’aide ?

    merci bcp

  35. XoraX

    si tu utilise prototype :

    Event.observe(window, 'load', function(){
    ...
    }

    sinon, Ă  chaque fois que tu veux ajouter un Ă©couteur :

    function addLoadEvent(func) {
      var oldfunc = window.onload || function(){} ;
      window.onload = function () {
        oldfunc();
        func();
      }
    }

    mais je crois que ton problĂšme c’est plutĂŽt, que tu charge du contenu en ajax donc l’apel Ă  window.onload ne se fait pas. Donc tu dois le faire toi-mĂȘme si tu le souhaite Ă  chaque fois que tu as fini un XHR tu lance window.onload();, tout simplement.

    en passan je ferme les commentaires pour cet article, allez voir la nouvelle version 😉

Les commentaires sont fermés.