CSS already injected

137 views
Skip to first unread message

Bart Butenaers

unread,
Jul 6, 2021, 1:41:18 AM7/6/21
to Blockly
Hi everybody,

I am adding some functionality in our applications, where users can compose (in some kind of graphical way) there toolbox.  And that works fine, except in this case:

  1. The current workspace is visible
  2. The user goes to the settings to add a new category to the toolbox, in which he uses the field-date npm module.
  3. All required libraries are loaded
  4. As soon as the date_compressed.js file (from that npm module) is being loaded, we get this error:
css_already_injected.png

I already tried to call workspace.dispose() before the libraries are loaded, but that doesn't help...

Does somebody know what I am doing wrong?

Thanks!!!
Bart

Neil Fraser

unread,
Jul 6, 2021, 3:54:46 AM7/6/21
to blo...@googlegroups.com
When injecting Blockly, you can choose to not inject CSS:

--
You received this message because you are subscribed to the Google Groups "Blockly" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blockly+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/blockly/d772ba90-b9ba-4ad6-a40d-6d3199e2b27dn%40googlegroups.com.


--

Bart Butenaers

unread,
Jul 6, 2021, 6:47:25 AM7/6/21
to Blockly
Hey Neil,
Thanks for the tip!
When I do it like this:

Blockly.inject('blocklyDiv', {
                ...
                css: false
            });

Then the error does not to appear anymore in the logs.
But now all my styling is gone, so I don't even see the flyouts anymore:

no_css.png
Is there an easy way for me to load the CSS somehow easily?
Thanks!
Bart

Bart Butenaers

unread,
Jul 10, 2021, 1:29:52 AM7/10/21
to Blockly
I have it now working by redesigning my application.  Every time the user returns from the configuration window (where he can compose the toolbox), I reload all Blockly libraries in the correct order.   This way the Blockly plugin code will be loaded without problems, since the CSS can still be changed (because the workspace is only created afterwards).

In case anybody ever needs it, I will explain here how I implemented it:

        var  lastScriptToLoad;

        // Remove all the custom blockly scripts from the previous time.
        // We can recognize the blockly scripts by the user attribute "data-custom_blockly_library" which we have set below in the code.
        $('script[data-custom_blockly_library=true]').remove();

        // Make sure that all standard Blockly library files are loaded FIRST AND IN THE CORRECT ORDER, and then the custom block libraries and translations.
        // The en.js file should be loaded before the blocks_compressed.js library, to avoid "No message string for..." console warnings.
        var resources = [
                "blockly-contrib/npm/blockly/blockly_compressed.js",    // Creates a global Blockly variable
                "blockly-contrib/npm/blockly/msg/en.js",                // Fills the Blockly.Msg with english translations
                "blockly-contrib/npm/blockly/blocks_compressed.js",
                "blockly-contrib/npm/blockly/javascript_compressed.js"
        ]

        // Now add all other required resources to the resources array (i.e. libraries and translation files that the user has been selected)
        ...

        // As soon as the toolbox files have been loaded, the javascript files for the categories will be loaded.
        // The javascript files will be loaded synchronous, because there is a dependency order that needs to be fullfilled.
        // However the files will be loaded in background, so we need to wait for an event that indicates that the script is loaded...
         resources.forEach(function(resource) {
                    // Make sure that all Blockly library files are loaded in the correct order.
                    // Don't use jQuery (see https://discourse.nodered.org/t/scope-of-variables-in-external-js-scripts/1048/2)
                    lastScriptToLoad = document.createElement('script');
                    lastScriptToLoad.type="text/javascript";
                    lastScriptToLoad.async = false; // Force synchronous loading, to load them in the correct order
                    lastScriptToLoad.src = file; 
                    // Set a user attribute on the script element, to allow us to identify this script afterwards as one of the blockly related libs
                    lastScriptToLoad.dataset.custom_blockly_library = true;
                    document.head.appendChild(lastScriptToLoad);
                }
            });
        });

        // The workspace can only be created when all script files have been loaded, otherwise errors will occur...
        lastScriptToLoad.onload = function() {
            // From here on the global Blockly variable exists, so you can optionally do some initialization here.  For example:
            Blockly.JavaScript.addReservedWords(['msg', 'flow', 'context', 'global']);
            
            // Create a new XML toolbox document
            var toolboxXmlDocument = document.implementation.createDocument("https://developers.google.com/blockly/xml", "xml", null);

            // Add the toolbox.xml files of all required libraries (which the user has selected to display) via toolboxXmlDocument.documentElement.appendChild(...)
            ...
            
            // Create the workspace as soon as the last script has been loaded.  
            ...           
        }

So for me this problem is solved ...

Bart

Beka Westberg

unread,
Jul 10, 2021, 10:28:28 AM7/10/21
to Blockly
Thanks for posting the full solution Bart! It's always really nice to come back to an old question and see the full code that someone used :D

Best,
--Beka

Reply all
Reply to author
Forward
0 new messages