Connect JavaScript Code and Blockly Code

574 views
Skip to first unread message

Clyde Eisenbeis

unread,
Mar 5, 2024, 9:07:40 AM3/5/24
to Blockly
I have written JavaScript code that moves a car on the screen with keyboard entries =>  https://snipboard.io/N7D5E4.jpg.
document.body.addEventListener("keydown", e =>
  {
      switch(e.key) {         
        case 's':
          fSpinCar360Deg();
          break;
        case 'f':
          fMoveForwardToEdge();
          break;
        case 'b':
          fMoveBackwardToEdge();
          break;
}
}

------------------------------
My Blockly code:
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Toolbox Customization Codelab</title>
    <script src="https://unpkg.com/blockly/blockly.min.js"></script>
    <link rel="stylesheet" href="toolbox_style.css">
    <script src="StartingScreen.js"></script>
    <script src="Simulator.js"></script>
    <script src="ForwardBackward.js"></script>
    <script src="TurnLeftRight.js"></script>
    <style>
      html,
      body {
        height: 100%;
      }
      body {
        background-color: #ffffff;
        font-family: sans-serif;
        overflow: hidden;
      }
      h1 {
        font-weight: normal;
        font-size: 140%;
        margin: 10px;
      }
      #blocklyDiv {
        float: bottom;
        height: 50%;
        width: 100%;
      }
    </style>
  </head>
  <body>
    <div id="blocklyDiv"></div>
    <script>      
      const nameToolbox = {
        // "categoryToolbox" is a Toolbox
        "kind": "categoryToolbox",
        "contents": [
          // Main menu
          {
            // "category" is a Menu item
            "kind": "category",
            // The word "Simulator" is displayed on the Main menu
            "name": "Simulator",
            "contents": [
              {
                // "block" creates a block on the screen
                "kind": "block",
                // "typeSimulator" is the block name found in a .js file
                "type": "typeSimulator"
              },
            ]
          },
          // Main menu
          {
            // "category" is a Menu item
            "kind": "category",
            // The word "Movement" is displayed on the Main menu
            "name": "Movement",
            "contents": [
              // Nested menu
              {                
                // "category" is a Menu item
                "kind": "category",
                // The words "Forward or backward" are displayed on the Nested menu
                "name": "Forward or backward",
                "contents": [
                  {
                    // "block" creates a block on the screen
                    "kind": "block",
                    // "typeForwardBackward" is the block name found in a .js file
                    "type": "typeForwardBackward"
                  }
                ]
              },
              // Nested menu
              {                
                // "category" is a Menu item
                "kind": "category",
                // The words "Turn left or right" are displayed on the Nested menu
                "name": "Turn left or right",
                "contents": [
                  {
                    // "block" creates a block on the screen
                    "kind": "block",
                    // "typeTurnLeftRight" is the block name found in a .js file
                    "type": "typeTurnLeftRight"
                  }
                ]
              }
            ]
          },
        ]
      }
      const workspace0 = Blockly.inject('blocklyDiv', {toolbox: nameToolbox});
      // Place a block on the starting screen
      Blockly.serialization.blocks.append({
          type: 'typeStartingScreen',
          // do not allow it to be deleted
          deletable: false,
          movable: false,
          editable: false,
      }, workspace0);
      workspace0.addChangeListener(Blockly.Events.disableOrphans);
    </script>
  </body>
</html>

'use strict';
// ... Names have been changed to clarify which are nemes
// ... Comments have been added to clarify actions
Blockly.defineBlocksWithJsonArray
([
  {
    // "typeStartingScreen" is the name for javascript.javascriptGenerator.forBlock{}
    "type": "typeStartingScreen",
    // The word "Simulator" is displayed on Block screen
    "message0": " Simulator %1 %2 %3 %4 %5",
    "args0": [
      {
        "type": "input_dummy"
      },
      {
        "type": "field_label_serializable",
        // "nameInitializationBlocks" is in javascript.javascriptGenerator.forBlock{}
        "name": "nameInitializationBlocks",
        // "The words "... Put initialization blocks here" are displayed on the Block screen
        "text": "... Put initialization blocks here"
      },
      {
        "type": "input_statement",
        // "nameInitializationBlocks" is in javascript.javascriptGenerator.forBlock{}
        "name": "nameInitializationBlocks"
      },
      {
        "type": "field_label_serializable",
        // "nameRunBlocks" is in javascript.javascriptGenerator.forBlock{}
        "name": "nameRunBlocks",
        // The words "... Put run blocks here" are displayed on the Block screen
        "text": "... Put run blocks here"
      },
      {
        "type": "input_statement",
        // "nameRunBlocks" is in javascript.javascriptGenerator.forBlock{}
        "name": "nameRunBlocks "
      },
    ],
    "colour": 290,
    "tooltip": "",
    "helpUrl": ""
  }
]);

// Used to generate and run JavaScript
javascript.javascriptGenerator.forBlock['typeStartingScreen'] = function(block, generator) {
  // Put initialization blocks here
  var field_initializationblocks = block.getFieldValue('nameInitializationBlocks');
  var statements_initializationblocks = generator.statementToCode(block, 'nameInitializationBlocks');
  // Put run blocks here
  var field__runblocks_ = block.getFieldValue('nameRunBlocks');
  var statements_runblocks_ = generator.statementToCode(block, 'nameRunBlocks ');
  // TODO: Assemble javascript into code variable.
  var code = '...\n';
  return code;
};
can result in this -> https://snipboard.io/03iGz1.jpg.

------------------------------
What Blockly websites describe how to execute the Blockly 
   "Forward or Backward - forward"
   "Turn left or right - left"
   "Forward or Backward - backward" 
that sends these Blockly commands to my JavaScript code?



Aaron Dodson

unread,
Mar 12, 2024, 6:46:53 PM3/12/24
to Blockly
Assuming you also have defined generators for your typeForwardBackward and typeTurnLeftRight blocks (needed for the statementToCode calls to work), you should just be able to return `${statements_initializationblocks}\n${statements_runblocks_}`; from your typeStartingScreen generator.

That will allow you to convert your Blockly program to Javascript; what you do with that Javascript is up to you, and in this case you'd most likely want to eval()it in the context of the car simulator, where fMoveForwardToEdge() and such are defined.

https://developers.google.com/blockly/guides/create-custom-blocks/code-generation/overview has more information about generators in general that might be useful as well.

Clyde Eisenbeis

unread,
Mar 19, 2024, 10:31:56 AM3/19/24
to Blockly
The car / street code I posted is this "index.html" file:
<html>
  <head>
      <meta charset="UTF-8">
      <meta name="viewport", content="width=device-width, initial-scale=1.0">
      <link rel="stylesheet" href="image.css">
  </head>
  <body>
      <div id="canvasContainer">
          <canvas id="canvas" width="900" height="520"></canvas>
          </div>
      <script src="image.js"></script>
  </body>
</html>
and this "image.js" file:
"use strict";const gcCanvas = document.getElementById('canvas');
  gcCanvas.width = 600;
  gcCanvas.height = 300;

const gcContext = gcCanvas.getContext('2d');
...

document.addEventListener('DOMContentLoaded', (ev) =>
  {
    gcBackgroundImage.onload = function ()
    {
      gcCarImage.onload = function ()
      {
        const cAspectRatio = gcBackgroundImage.naturalWidth / gcBackgroundImage.naturalHeight;
...
      }
      gcCarImage.src = "Car.jpg";
    }
    gcBackgroundImage.src = "Streets.jpg";
  }
)
document.body.addEventListener("keydown", e =>  {
    let lCarCenterX;
...
    e.preventDefault();
    if(glTimeoutIsOccuringFlag === false) {
      switch(e.key) {
        case 's':
          fSpinCar360Deg();
          break;
        case 'f':
          fMoveForwardToEdge();
          break;
        case 'b':
          fMoveBackwardToEdge();
          break;
...
      }  
    }
  }
)
function fMoveForwardToEdge()
{
...
}
function fMoveBackwardToEdge()
{
...
}
function fSpinCar360Deg()
{
...
}

1) "Assuming you also have defined generators typeForwardBackward

 Where / how do I define generators?  Inside the StartingScreen.js which contains the Blockly code.

2) "will allow you to convert your Blockly program to Javascript"  

Is the conversion a manual command, or is there code inside which files?

3) "be able to return `${statements_initializationblocks}\n${statements_runblocks_}`; from your typeStartingScreen generator."   

Where do I place this code?

Thanks!

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Maribeth Moffatt

unread,
Mar 19, 2024, 3:54:59 PM3/19/24
to Blockly
Hello Clyde,

Have you read through the Code Generation docs that Aaron linked you to? They explain the basics of how and when to do code generation. It answers most of your questions. As for which files to write your code generators in, that is up to you, as we've discussed before. How your organize your own code is your own responsibility.

The most important thing to remember is that Blockly does not "run" or "execute" blocks. Blockly provides ways to convert blocks into text. Running that text as code is your own responsibility. 

Best,
Maribeth

Clyde Eisenbeis

unread,
Mar 20, 2024, 10:48:58 AM3/20/24
to Blockly
I have read the contents of that site.  However, the descriptions are not clear to me. 

For example, "You can't "run" blocks directly. Instead you generate code strings, and then execute those."  That does not tell me where to place that code.  Or if it is separate code that is not placed inside the Blockly code.

Under the Code Generator sections, is this -> "import {javascriptGenerator} from 'blockly/javascript'; "
If so, where?  Before or inside
Blockly.defineBlocksWithJsonArray
(...);
This .js code in my first post.

Same question for
-> "const code = javascriptGenerator.workspaceToCode(myWorkspace);"
-> "import {javascriptGenerator} from 'blockly/javascript';"
-> "const jsCode = javascriptGenerator.workspaceToCode(workspace)"

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Maribeth Moffatt

unread,
Mar 20, 2024, 2:12:15 PM3/20/24
to Blockly
Hello Clyde,

Blockly.defineBlocksWithJsonArray is a function. Specifically, it is a function that allows you to pass in an array of JSON that defines blocks. You cannot write other JavaScript code inside this function call. That function is just one small part of the Blockly API. Blockly is a library with many APIs. There are many different functions you can call to accomplish different tasks. The documentation explains which functions to call to accomplish which tasks. Unless you read something that says otherwise, there is no reason you should write any specific JavaScript code inside a function call; indeed, this is likely to be invalid JavaScript.

The documentation does not tell you where to write your code because that is not a concern of the Blockly library. We are unable to provide support in the form of "write this exact line of code in this exact location." The lines of code you have copied are lines of JavaScript code that should be executed in order to convert your blocks to code. You can put them in whatever file you want. It is your job to decide how to split up your code organization and to organize in what order your JavaScript files are loaded. If you need additional help with that topic, unfortunately the Blockly forum is not the right place for that kind of assistance because it is a question about web development, not Blockly specifically.

If you decide to write all of your code in one JavaScript file, it will generally be executed from top-to-bottom. That means you need to write your code in a logical order. You must define your blocks first before a user can drag them to a workspace. The workspace must exist before you can convert it to code.

Since you are loading Blockly with script tags from unpkg, you should not use "import" statements. Click the "unpkg" tab on the code sample to see the code sample that applies to your situation.

Best,
Maribeth

Clyde Eisenbeis

unread,
Mar 22, 2024, 9:26:21 AM3/22/24
to Blockly
1) "Blockly.defineBlocksWithJsonArray is a function ... no reason you should write any specific JavaScript code inside a function call ...."

Understood.

2) "The lines of code you have copied are lines of JavaScript code that should be executed in order to convert your blocks to code. You can put them in whatever file you want."

I do not understand.   I presume that I need to use the Blockly Code Generator, to convert my existing Blockly index.html and StartingScreen.js files into code that I then add to my car / street code? 

3) "If you decide to write all of your code in one JavaScript file ... define your blocks first before a user can drag them to a workspace. The workspace must exist before you can convert it to code. "

My Blockly code is a combination of a HTML file and a JS file.  Do I need to move the HTML code into the JS file so I have only a JS file? 

4) Under the Unpkg tab, I see:
    <script src="https://unpkg.com/blockly"></script>
    <script src="https://unpkg.com/blockly/javascript_compressed"></script>
    ...
    const jsCode = javascript.javascriptGenerator.workspaceToCode(workspace);

What should I do after I see the contents of the Unpkg tab?

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Maribeth Moffatt

unread,
Mar 22, 2024, 12:50:31 PM3/22/24
to Blockly
2. Your index.html and startingScreen.js files create a workspace and the blocks that might be on it. The Blockly code generator converts blocks that are on the workspace to code. 
3. Apologies, no. I'm not suggesting that you should rewrite or move your code anywhere. It was a hypothetical to explain the order in which your code will be executed. What I am saying is that you need to define your blocks and their block-code generator functions before you convert the workspace to code. I don't know which file it's in, but the very last bit of the code you posted in the first post:

javascript.javascriptGenerator.forBlock['typeStartingScreen'] = function(block, generator) { ...

is a block-code generator function for the block 'typeStartingScreen'. That function will be called when you call `workspaceToCode` and there is a `typeStartingScreen` block on the workspace. Therefore, you must call `workspaceToCode` sometime after you've written that block-code generator function. You also need the workspace to exist. You inject the workspace at the very end of index.html. That is the last thing that will run when your page is loaded. So you can add new logic that depends on the workspace existing there, if you want. Does that make sense?

Note that when you call `workspaceToCode`, all the blocks on the workspace as it exists right that very moment will be converted to code. If you call it as soon as the page loads, the user hasn't had time to put any blocks on the workspace. Maybe review the Getting Started codelab to see how that sample application deals with this. Or put aside this problem for later, and first just convert the workspace to code at all before trying to do it at the right moment.

4. The unpkg tab is the one that shows you the Blockly APIs that convert the workspace to code. Use this code in your application to convert the workspace to code. You need to include the script tag for the generator you want (javascript), and you have to do that after the script tag that loads Blockly itself (which is already in your application, no need to write it twice). Then write the `const jsCode = javascript.javascriptGenerator.workspaceToCode(workspace);` line in an appropriate location as discussed above. Note that you called your workspace `workspace0`, not just `workspace`, so update the variable accordingly.

Best,
Maribeth

Clyde Eisenbeis

unread,
Mar 24, 2024, 9:15:54 AM3/24/24
to Blockly
I modified the index.html to this:
<!DOCTYPE html>
<!-- Names have been changed to clarify which are nemes
     Comments have been added to clarify actions -->
<html>
  <head>
    <meta charset="utf-8">
    <title>Toolbox Customization Codelab</title>
    <!-- <script src="https://unpkg.com/blockly/blockly.min.js"></script> -->
    <script src="https://unpkg.com/blockly"></script>
      const workspace = Blockly.inject('blocklyDiv', {toolbox: nameToolbox});
      // Place a block on the starting screen
      Blockly.serialization.blocks.append({
          type: 'typeStartingScreen',
          // do not allow it to be deleted
          deletable: false,
          movable: false,
          editable: false,
      }, workspace);
      workspace.addChangeListener(Blockly.Events.disableOrphans);
      const jsCode = javascript.javascriptGenerator.workspaceToCode(workspace);
    </script>
  </body>
</html>

It displays the Blockly menu correctly on the Chrome browser.  The Debug Console ->
Could not read source map for https://unpkg.com/blockly: Unexpected
404 response from https://unpkg.com/javascript_compressed.js.map: Cannot find package javascript_compressed.js.map@latest

Also, should the Code Generator produce a JS file?

Please advise.  Thanks!

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Maribeth Moffatt

unread,
Mar 24, 2024, 10:23:59 PM3/24/24
to Blockly
You can ignore the message about sourcemaps. It is not relevant.

The code generator does not produce a file. The blocks on the workspace are converted to code and the result is stored as a string in the variable you've called 'jsCode'.

Best,
Maribeth

Clyde Eisenbeis

unread,
Mar 25, 2024, 8:54:18 AM3/25/24
to Blockly
1) I've entered the  Code Generator code correctly?

2) Where do I find that variable named jsCode?

3) How do I combine this code with my JavaScript Code for the car / street?

4) How do the sequence of Block commands from jsCode get passed to my car / street code?

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Maribeth Moffatt

unread,
Mar 25, 2024, 1:58:04 PM3/25/24
to Blockly
1. Yes
2. You have defined this variable in your own index.html.
3. You need to define block-code generators for each of your custom blocks. The block-code generators should return JavaScript code that corresponds to the custom block. If you have a "turn left" block, your block-code generator might return the string `turnLeft()`. Actually defining the function `turnLeft` and what it does is outside the scope of Blockly and up to you and your application. There are many details for doing code generation which are linked from the code generation documentation above.
4. Blockly converts the blocks to code and returns that code to you as a string. What you do with it after that is up to you and not something we can provide in-depth support for. The quick and dirty approach is to use eval. This is not safe for a production-ready application, but is fine while you are prototyping or working on something for personal use. 

I would again encourage you to look at the getting started codelab's complete code to see its approach to code generation and execution.

Best,
Maribeth

Clyde Eisenbeis

unread,
Mar 26, 2024, 8:10:57 AM3/26/24
to Blockly
1) Good.

2) "You have defined this variable in your own index.html."  I understand that jsCode is defined.  I have two index.html files -> one with Blockly and another with the car / street.  Should these two indexes be combined into one index.html?

3) "You need to define block-code generators for each of your custom blocks".  I do not understand.  I thought that the code I added in the previous example already did that?  What do I need to add to define block-code generators for every custom block?  Exactly where do I put that code?

4) "Blockly converts the blocks to code and returns that code to you as a string."  I presume that string is this code for this canvas image -> https://snipboard.io/cRIbJS.jpg.  Where do I find that string?  How can I look at that string?  What code words do I put in my car / street JavaScript code to access that string?

5) "... getting started codelab's complete code to see its approach to code generation and execution ...."  Which codelab complete code?  What name?  There are many.  Thanks!

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Clyde Eisenbeis

unread,
Apr 10, 2024, 5:05:54 PM4/10/24
to Blockly
Don't know if you received this email.  Thanks!

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Maribeth Moffatt

unread,
Apr 10, 2024, 5:25:49 PM4/10/24
to Blockly
2. Generally, you can only open one HTML file in a browser at a time. This isn't 100% true in all cases but those other cases would be using a more advanced setup than you have. Think of your index.html file as representing your web page. If you have two of them, that implies you're working on two different web pages. Again, this is not a Blockly-specific question, so I'm going to encourage you to do more reading about web application organization and structure somewhere else as we don't have the resources to answer those types of questions on this forum.

3. In your very first message in this thread, your last file includes 
javascript.javascriptGenerator.forBlock['typeStartingScreen'] = function(block, generator) {
// ...snippet...
// TODO: Assemble javascript into code variable.
  var code = '...\n';
  return code;
}

This is your block-code generator function for the block called 'typeStartingScreen'. When you convert that block, the code it will be converted to is "...\n" because that's what your block-code generator function returns. You need to update this function to return the correct code for the block. You also need to define similar functions for any other custom blocks.

4. The string is returned when you call `workspaceToCode`.

5. The Getting Started codelab, which I linked in a previous message.

Best,
Maribeth

Clyde Eisenbeis

unread,
Apr 12, 2024, 10:00:54 AM4/12/24
to Blockly
2) I've written HTML code for more than 30 years.  I'm not sure how to combine the Blockly HTML with the Car / Street HTML.   Should I just concatenate the two HTML files?

3) "... When you convert that block, the code it will be converted to is "...\n" because that's what your block-code generator function returns."  Where do I find that code to look at it?

4) "The string is returned when you call `workspaceToCode`."  Where do I call `workspaceToCode`?  In the .js file?  How do I look at the contents?

5) The original question was, "How do the sequence of Block commands from jsCode get passed to my Car / Street code? ".  I have read "Getting Started codelab" multiple times.  That does not tell me exactly what I should do.  Is there a Codelab example, in "blockly-samples-master\examples"?  If not, could someone provide me with that snippet of code?

Thanks!

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Maribeth Moffatt

unread,
Apr 12, 2024, 12:59:20 PM4/12/24
to Blockly
2. If you want the Blockly toolbox and the car canvas to be on the same web page, then yes they need to be in the same HTML file. How you combine them depends on how you want your web page to look.

3. That code is in your first message in this thread. I do not know where in your application you have written it.

4. You call `workspaceToCode` at the point in which you want to convert your workspace to code. That may be when the user clicks a "run" button, for example. The code will be returned from that function as a string. You can log it to the console, write it to your html page, use the browser's debugger, however you would normally test what your javascript does.

5. Here is the flow of writing a Blockly application and running the code:

- You design custom blocks. As an example, let's say you have a block that will turn a robot left. The block says "turn left." This is accomplished with the block definition.
- You write block-code generators for each of your custom blocks. Your turn left block might output the code `turnLeft();`. More complex blocks will return more complex code, which might use the values of connected blocks, or have fields where the user input values. Converting those connected blocks and fields to code in the block-code generator function is covered in the Code Generation docs.
- You call `workspaceToCode` to convert the current workspace of blocks to code. This function calls the block-code generator function for each of the blocks on the workspace at the time you call it. So you need to call it when you're ready to convert the workspace to code. Perhaps you provide a "run" button in your application. When a user clicks this button, you generate the code and run it. Let's say the workspace only contains a single "turn left" block. When you generate code for the workspace, you get the output `turnLeft();` as a string.
----- Everything above this line uses Blockly APIs. Everything below it does not use Blockly APIs. It is up to you to design this part, and we can only provide limited support for answering questions related to those topics. ------
-  `turnLeft()` is calling a function, which you must define. This function would contain the code that actually moves your robot across the screen. Implementing the robot and moving it are not related to Blockly. We don't provide tools to do that. You will have to write this yourself.
- You will execute the JavaScript code returned by Blockly. That means actually running the `turnLeft()` code that resulted from converting the blocks to JavaScript. There are multiple ways to execute JavaScript on a web page. A quick and dirty way to do it is to use eval. This is also not a Blockly API and you need to write this execution code yourself.

This flow is illustrated in the getting started codelab. You can read the complete code for it here. FYI, each of the codelabs explains where to find its starter and complete code in the "Setup" step of the codelab.

Best,
Maribeth

Clyde Eisenbeis

unread,
Apr 13, 2024, 1:27:28 PM4/13/24
to Blockly
I decided to start over, using the files in the "...\getting-started-codelab\complete-code" folder.  I'm adding comments to that Blockly "getting-started-codelab" folder files code.

Comments added to index.html
<body mode="maker">
  <!-- Title background color -->
  <header class="mdl-color--cyan-500">
    <!-- Initial Title -->
    <h1 class="mode-maker">Music Maker</h1>
    <!-- Title after selecting a colored number -->
    <h1 class="mode-edit mode-blockly">Music Maker Configuration</h1>
  </header>

...
  <main>
    <!-- Initial Button -->
    <button class="mode-maker mdl-button" id="edit">Edit</button>
    <!-- Button after selecting Edit button -->
    <button class="mode-edit mdl-button mdl-js-button" id="done">Done</button>
    <!-- Message after selecting Edit button -->
    <p class="hint mode-edit">Tap any button to edit its code. <br/>When complete, press Done.</p>
    <!-- Button after selecting colored number -->
    <button class="mode-blockly mdl-button mdl-js-button" id="save">Save</button>

    <!-- Initial display on screen -->
    <div class="maker">
      <div>
The --- mode="maker" --- and --- "mode-maker" --- are found in index.css and main.js.

Comments added to index.css
.mode-edit,
/* Defines mode-maker as a class */
.mode-maker,
.mode-blockly {
  display: none;
}
/* Assigns the mode="maker" name to the .mode-maker class */
[mode="maker"] .mode-maker,
[mode="edit"] .mode-edit,
[mode="blockly"] .mode-blockly {
  display: block;
}

Comments added to main.js
  // Called by a "mouse click" via an EventListener
  function enableMakerMode() {
    document.body.setAttribute('mode', 'maker');
    document.querySelectorAll('.button').forEach(btn => {
      btn.addEventListener('click', handlePlay);
      btn.removeEventListener('click', enableBlocklyMode);
    });
  }

...
  // Assigning a button ID label "mouse click" to a function
  document.querySelector('#edit').addEventListener('click', enableEditMode);
  document.querySelector('#done').addEventListener('click', enableMakerMode);
  document.querySelector('#save').addEventListener('click', handleSave);

I cannot find  --- [mode="maker"] --- or --- .mode-maker --- at the W3Schools website.  It appears these are Blockly parameters.  Correct?

I see that "mdl-color" specifies colors, but do not know were that is defined?  Ditto for "mdl-js-button"?

Are the comments in the code correct?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Mark Friedman

unread,
Apr 13, 2024, 8:14:17 PM4/13/24
to blo...@googlegroups.com
Clyde,

  None of the code that you show has anything to do with Blockly, per se.  That's all just HTML, CSS and JavaScript for setting up the styles and buttons for the Music Maker app.  None of it affects the Blockly workspace.  The "mdl-..." references are to CSS style items defined in the "https://code.getmdl.io/1.2.1/material.indigo-pink.min.css" stylesheet link tha appears in the index.html file, above the body section that you quote in your post.  You can read more about CSS and styles here, but I'll warn you that it's a large and somewhat complex topic.

-Mark


--
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/f4a2514b-776a-459b-8c14-9b59dd6c364en%40googlegroups.com.
Message has been deleted

Maribeth Moffatt

unread,
Apr 15, 2024, 12:01:13 PM4/15/24
to Blockly
Hello Clyde,

Mark is correct. The code you've shown here is just setting up the HTML, CSS, and JavaScript for the styles and buttons of the app used in the codelab. If you would like more assistance in working with CSS selectors or other non-Blockly-specific topics, it would be best for you to seek that elsewhere as we are not equipped to answer all kinds of web development questions in this forum. We only have the capacity to answer questions related to using Blockly APIs.

Best,
Maribeth

Clyde Eisenbeis

unread,
Apr 20, 2024, 1:26:54 PM4/20/24
to Blockly
I posted some questions on the Web Design Group forum => https://forums.htmlhelp.com/index.php?showtopic=61462.

I'm interested in your thoughts about the "mode" comments.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Maribeth Moffatt

unread,
Apr 22, 2024, 11:23:06 AM4/22/24
to Blockly
They are correct that "mode" is not a standard attribute. However, unless you are running your HTML through an HTML validator, this is unlikely to be a problem. It being nonstandard means the browser has no built-in reaction to the attribute being set, which is fine. CSS selectors that work on attributes will still work on non-standard attributes, which is the main thing we're doing with it here. If I were writing this app, I probably would have chosen a different approach, but I don't think there is anything wrong with the current one either. Using nonstandard attributes has become more common especially for popular frameworks like Angular and is now supported in custom elements.

In the end, this is simply a quirk of the sample app that is used in the codelab. It is not actually related to the Blockly library at all, so you can either ignore it or you can change the app however you'd like to use a different approach to toggle between maker, edit, and blockly modes.

Best,
Maribeth

Clyde Eisenbeis

unread,
Apr 23, 2024, 10:00:01 AM4/23/24
to Blockly
What section of code (perhaps JS) uses this attribute, and how is it used?  What would happen if this attribute were not in the HTML code?   

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Maribeth Moffatt

unread,
Apr 23, 2024, 2:12:46 PM4/23/24
to Blockly
This app has 3 different "modes" and the HTML for all 3 is present on the same page: maker, edit, and blockly mode. Only one of the modes is active at one time; the other two will be hidden. The CSS hides all of them first, and the "mode" attribute is used in a CSS selector to make the currently active mode visible again. The mode attribute is in the initial HTML to make one of those modes show up by default, and there is JavaScript to change the attribute value when another mode is selected. If you removed the mode attribute from all of the HTML, JavaScript, and CSS references to it, the page would not look right because all 3 modes would show up simultaneously. You could accomplish this hiding and showing of the different pieces of the page another way if you so choose. But this functionality is related to manipulating the DOM in JavaScript, and is not a Blockly-specific topic. If you would like to change how that part of the codelab app works, or you have additional questions about how to manipulate the DOM from JavaScript/CSS, we request that you seek support for that elsewhere as we do not have the resources to provide support for general web development questions in this forum.

Best,
Maribeth

Clyde Eisenbeis

unread,
Apr 25, 2024, 9:55:22 AM4/25/24
to Blockly
Thanks for clarifying!  I don't plan to change anything.  I'm planning to add comments to clarify the code.  This is how I learn!

.mode-maker,
.mode-edit,
.mode-blockly {
  display: none;
}

1) The "." makes these names as Class selectors.

---
[mode="maker"] .mode-maker,
[mode="edit"] .mode-edit,
[mode="blockly"] .mode-blockly {
  display: block;
}

2) A mode name is assigned to every Class selector.  

---
    <div class="maker">

3) The "maker" mode name is assigned to a <div class ...> 

---
    <button class="mode-maker mdl-button" id="edit">Edit</button>

4) The "edit" mode name is assigned to a <button class ... >  ... the "id" of the Edit button.
---

5) While I see the "mode-blockly" name, I'm unable to find a "blockly" mode name assigned to a class.

---
6) When I change

<body mode="maker">

to

<body>

the code still works.

---
I'm interested in your comments on 1) through 6).  Thanks!


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Clyde Eisenbeis

unread,
May 6, 2024, 7:45:19 AM5/6/24
to Blockly
Curious about the status?

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Beka Westberg

unread,
May 6, 2024, 12:24:37 PM5/6/24
to Blockly
Hello, as Maribeth said previously:

> [If] you have additional questions about how to manipulate the DOM from JavaScript/CSS, we request that you seek support for that elsewhere as we do not have the resources to provide support for general web development questions in this forum.

I recommend asking on stack overflow!

Best wishes,
--Beka

Clyde Eisenbeis

unread,
May 7, 2024, 8:11:21 AM5/7/24
to Blockly
Maribeth's post: 

"The CSS hides all of them first, and the "mode" attribute is used in a CSS selector to make the currently active mode visible again.

The mode attribute is in the initial HTML to make one of those modes show up by default, and there is JavaScript to change the attribute value when another mode is selected.

If you removed the mode attribute from all of the HTML, JavaScript, and CSS references to it, the page would not look right because all 3 modes would show up simultaneously.

---
My response:

6) When I change
<body mode="maker">
to
<body>
the code still works.

This does not appear to match Maribeth's post.  Please clarify.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Message has been deleted

Maribeth Moffatt

unread,
May 8, 2024, 2:09:13 PM5/8/24
to Blockly
Hello Clyde,

As I've said, we simply do not have the resources to answer non-Blockly-related questions in this forum. I previously provided information about how the codelab works as a courtesy only. If your questions are about HTML/CSS generally and not Blockly, then in the future we may not respond to those emails. Thank you for your understanding.

Best,
Maribeth
Reply all
Reply to author
Forward
0 new messages