Dynamically loading a script changes its behaviour

烂漫一生 提交于 2020-01-16 05:31:10

问题


I wanted paperjs to load after a button is pressed to turn on animations but it seems the paperscript doesn't work if paper is loaded after page load.

If you comment out the setTimeout and uncomment the direct $.getScript - paperjs will fire the alert('hi'). I don't get it.

<html>
    <head>
        <script src="http://code.jquery.com/jquery-latest.js"></script>
        <script>
            $(document).ready(function () {
                var paperUrl = 'http://cdnjs.cloudflare.com/ajax/libs/paper.js/0.22/paper.js';
                $("#jq").text("jQuery is now loaded.")
                var lateLoad = function() {
                    $.getScript(paperUrl, function() {
                        $("#pp").text("Paperjs is now loaded.");
                    });
                };
                //setTimeout(lateLoad, 100);
                $.getScript(paperUrl, function() {
                    $("#pp").text("Paperjs is now loaded.");
                });
            });
        </script>
    </head>
    <body>
        <script type="text/paperscript" canvas="myCanvas">
            $('body').css({"background-color": "#999"});
            alert('hi!');
        </script>
        <p id="jq">jQuery NOT loaded yet.</p>
        <p id="pp">Paperjs NOT loaded yet.</p>
    </body>
</html>

I'm using Chrome 23.0.1271.97 m on Windows 7 x64. Anybody have an idea what's going on here?


回答1:


I think I figured out a workaround as well - paper.PaperScript.load() or to elaborate:

<html>
    <head>
        <script src="http://code.jquery.com/jquery-latest.js"></script>
        <script>
            $(document).ready(function () {
                $("#jq").text("jQuery is now loaded.")
                var paperUrl = 'http://cdnjs.cloudflare.com/ajax/libs/paper.js/0.22/paper.js';
                var lateLoad = function() {
                    $.getScript(paper_url, function() { 
                        $("#pp").text("Paperjs is now loaded.");
                        paper.PaperScript.load(); // <-- The fix!
                    });
                };
                setTimeout(lateLoad, 1000);
                //$.getScript(paperUrl, function() {
                //    $("#pp").text("Paperjs is now loaded.");
                //});
            });
        </script>
    </head>
    <body>
        <script type="text/paperscript" canvas="myCanvas">
            $('body').css({"background-color": "#999"});
            alert('hi!');
        </script>
        <p id="jq">jQuery NOT loaded yet.</p>
        <p id="pp">Paperjs NOT loaded yet.</p>
    </body>
</html>

That causes paperscript to scan for all the paperscripts. I found it at https://github.com/paperjs/paper.js/blob/master/src/core/PaperScript.js#L270 while googling for "paperscript" in the github repo. Though it still doesn't explain why paper doesn't do the load() on its own when dynamically loaded.

EDIT - I understand what went wrong. It's related to https://github.com/jquery/jquery/blob/master/src/core.js#L768 because paperjs doesn't check if the window loaded event had already fired i.e document.readyState === "complete". I submitted a pull request to paperjs https://github.com/paperjs/paper.js/pull/156




回答2:


I think it is easier to load it via require.js. All you need is a require.config object, defined in e.g. main.js:

requirejs.config({
    paths : {   
        'jquery' : "path/to/jquery"
        'paper' : "path/to/paper"
    },
    shim: {
        'jquery' : {
            exports: 'jQuery'
        },
        'paper' : {
            exports: 'paper'
        }
    }
});

You will need to load require.js with the above config via the data-main attribute:

<script data-main="scripts/main.js" src="scripts/require.js"></script>

Then you define a module (e.g. 'paperStuff') where your paper logic will be:

define(['jquery', 'paper'], function($, paper) {
   // do some cool stuff
});

When you want to load your paperStuff, you just do

var paperStuff = require('paperStuff');
...



回答3:


Move your paperscript code into an external file (i.e. pstest.js) and modify your lateLoad to:

var lateLoad = function() {
    $.getScript('http://cdnjs.cloudflare.com/ajax/libs/paper.js/0.22/paper.js',
    function() {
      $("#pp").text("Paperjs is now loaded.");
      $.getScript("pstest.js");
    } )
}


来源:https://stackoverflow.com/questions/14110205/dynamically-loading-a-script-changes-its-behaviour

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!