Instability when loading Jquery dynamically in window.load() in Firefox

Asked

Viewed 494 times

1

I have a feature where depending on the situation I should declare the Jquery library and some other scripts, such as the script Alert.js than a class of the same name. I have tested this functionality in Google Chrome and Firefox, at first the scripts are always loaded correctly before the execution of the function/class Alert(), but in Firefox the scripts are loaded in an unstable way, that is, when the Alert function is executed, many times jQuery is not yet available, being necessary to reload the page so that the second time it works properly.

To clarify further, the error returned by Firefox in the console are as follows:

First:

ReferenceError: jQuery is not defined

According to:

TypeError: $(...).dialog is not a function
$("#dialog-message").dialog(arrayPropriedades);

The second error code is within the Alert class, and $.dialog() is a native function of Jquery UI that was not loaded due to the first error stating that jQuery had not yet been loaded.

See below the code of this functionality:

if (typeof (Alert) === 'undefined') {

    var scripts = [
        DIR_JS_LIB + 'lib/jquery/jquery.min.js',
        DIR_JS_LIB + 'lib/jquery/jquery-ui/jquery-ui.min.js',
        DIR_JS_LIB + 'scripts/componentes/dialog/AcaoJanela.js',
        DIR_JS_LIB + 'scripts/componentes/dialog/Botao.js',
        DIR_JS_LIB + 'scripts/componentes/dialog/Dialog.js',
        DIR_JS_LIB + 'scripts/componentes/dialog/Alert.js'
    ];

    for (var i = 0; i < scripts.length; i++) {
        include(scripts[i]);
    }

}
window.onload = function () {

    Alert(window.mensagem, window.titulo, window.botoes);
}

function include(file_path) {
    var j = document.createElement("script");
    j.src = file_path;
    document.getElementsByTagName('head')[0].appendChild(j);
}

PHP code that executes the above script (whose name is defined by the variable $this->path_load_script):

$str .= '<link rel="stylesheet" type="text/css" href="/app/assets/css/styles.css"/>'
                . '<link rel="stylesheet" type="text/css" href="' . DIR_JS_LIB . 'lib/jquery/jquery-ui/jquery-ui.custom.min.css" />'
                . "<script>"
                . "DIR_JS_LIB = '" . DIR_JS_LIB . "';\n"
                . "isColetor = " . (isColetor() ? 'true' : 'false') . ";\n"
                . "mensagem = '" . $this->getMensagem() . "';\n"
                . "titulo = '" . $this->getTitulo() . "';\n"
                . "botoes = {" . implode(',', $this->getBotoes()) . "};\n"
                . "try{\n"
                . get_called_class() . "(mensagem, titulo, botoes);\n"
                . "} catch(err) {\n"
                . "var script = document.createElement('script');"
                . "script.src='" . $this->path_load_script . "';\n"
                . " document.getElementsByTagName('head')[0].appendChild(script);\n"
                . "}\n"
                . "</script>\n";
  • Try to put the functions inside the ready jQuery.

  • There would be no way, because the error occurs when Jquery has not yet been loaded, so the ready function is not yet available.

  • Hmm, got it. To check if jQuery was loaded just do if (window.jQuery) { / jQuery carregado }

  • @mayconfsbrite of these files always need jQuery? or have cases where you do not want to load jQuery?

  • @Sergio this above script always needs Jquery yes. Its function is basically this, to display Dialogs (Alert) on pages that are outside the application template, because in the template jQuery is already loaded instantly.

  • 1

    If you always need jQuery I suggest you click on the head with your own link. In the head the load is synchronous, and avoid these errors. When it says "in the template jQuery is already loaded instantly" it means that there is another jQuery or refers to what is in your code in the question?

  • @Sergio actually there are two situations in my application. Pages that are displayed within a template with header, figure and menu, in which case the scripts are statically loaded into the <head> in the template. And the other situation are pages that are loaded outside the template, only for Dialogs display, so I have to declare the scripts dynamically according to the above code.

  • Tip: You can edit your question and include this information you’re passing through the comments. It makes it better for other people to understand the problem. ;)

  • @mayconfsbrito and these dialogues are iframes? or content that is part of the HTML page?

  • @Earendul thanks for the tip, I will update the question soon.

  • @Earendul good suggestion. And I’ll delete the questions/comment as soon as the answer is in the question.

  • @Sergio are Dialogs of Jquery-UI, I even noticed another error saying that the $.dialog() function does not exist, being this native of Jquery UI. I will enter this information in the question.

  • @mayconfsbrite if these dialogues are .dialog() then join jQuery and UI in the head (so they load syncrons), and the rest as you have in question and problem solved. Right?

  • @Would it be possible for Sergio not to add jQuery and jQueryUI directly to the head in a static way? Because this code is generated by my PHP application that prints the dialog both outside the template and inside.

  • @mayconfsbrito join the PHP code in question. But if in any case you need jQuery then it is best to join in the head. Otherwise you will need to setInterval to know when the script loaded and be able to load the next ones, cascade type, and is less elegant (if not strictly necessary).

  • @Sergio edited and put the PHP code there, the problem is that this app is a very big framewok and one thing is pulling the other. But I believe that the problem focuses only there on javascript and jquery.

Show 12 more comments

1 answer

0


In parallel to this topic I opened another post on Stack Overflow international and got the answer from the solution suggested by the user Master Slave. Click here to see the topic with the proposed solution.

To illustrate better I will post below the code that solved my problem:

window.onload = function () {

    var scripts = [
        DIR_JS_LIB + 'lib/jquery/jquery.min.js',
        DIR_JS_LIB + 'lib/jquery/jquery-ui/jquery-ui.min.js',
        DIR_JS_LIB + 'scripts/componentes/dialog/AcaoJanela.js',
        DIR_JS_LIB + 'scripts/componentes/dialog/Botao.js',
        DIR_JS_LIB + 'scripts/componentes/dialog/Dialog.js',
        DIR_JS_LIB + 'scripts/componentes/dialog/Alert.js'
    ];

    include(scripts[0], function () {
        include(scripts[1], function () {
            include(scripts[2], function () {
                include(scripts[3], function () {
                    include(scripts[4], function () {
                        include(scripts[5], function () {
                            Alert(window.mensagem, window.titulo, window.botoes);
                        });
                    });
                });
            });
        });
    });

}

function include(filename, callback) {
    var fileref = document.createElement('script');
    fileref.setAttribute("type", "text/javascript");
    fileref.setAttribute("src", filename);
    if (fileref.readyState) {
        fileref.onreadystatechange = function () { /*IE*/
            if (fileref.readyState == "loaded" || fileref.readyState == "complete") {
                fileref.onreadystatechange = null;
                callback();
            }
        }
    } else {
        fileref.onload = function () {  /*Other browsers*/
            callback();
        }
    }

    if (typeof fileref != "undefined")
        (document.getElementsByTagName("head")[0] || document.documentElement).appendChild(fileref)
}

Thank you all for your help.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.