Temporarily stop propagating events

120 views
Skip to first unread message

Bart Butenaers

unread,
Jul 18, 2018, 4:56:03 PM7/18/18
to Blockly
Hi everybody,

My Blockly integration for Node-Red is almost complete.  However I'm not getting the last exception solved:


Will try to explain what happens:



  1. A user can draw a flow in the Node-Red flow editor, which responds to keydown events (e.g. 'D' to delete the currently selected node, ...).  When the blockly node is double clicked, a popup will appear with the Blockly editor.
  2. The user can draw his business logic in the Blockly editor.  As soon as the user changes the text and presses 'Enter', Node-Red will receive the keydown event from Blockly and the error will occur in the log (since the setup isn't as expected by Node-Red).
  3. When the 'Done' button is pressed, the generated Javascript will be run in the blockly node (when an input message arrives on it's input port).
So it seemed to me that I could solve this, by making sure that the Blockly keydown events won't be propagated upwards into the DOM tree to Node-Red.  Tried to do this by running following code snippet when the popup is opened:

            node.originalKeyDownHandler = Blockly.onKeyDown_;
           
Blockly.onKeyDown_ = function(e) {
                node
.originalKeyDownHandler(e);
               
debugger;
               
                e
.stopPropagation();
           
}

I store temporary the original Blockly keydown handler and set my own handler.  In my handler I first call the orginal handler, to make sure that the Blockly editor keeps reacting to keydown events.  Afterwards I specify that the event shouldn't be propagated further.  THIS WORKS FINE: the keydown events aren't received by Node-Red anymore, and no error appears anymore in my log.

When the popup is closed, I restore the original event handler (to make sure that my stopPropagation isn't called anymore):

Blockly.onKeyDown_ = node.originalKeyDownHandler;

However THIS DOESN'T WORK: the keydown events aren't received anymore by Node-Red, so the Node-Red editor doesn't respond to key events.  Reason is that Blockly keeps calling my own handler, so the stopPropagation keeps being executed from here:


Do I have to do this in another way (addListener, removeListener??).  Would be nice if somebody could help me out...

Thanks !!!
Bart

Bart Butenaers

unread,
Jul 20, 2018, 6:19:49 PM7/20/18
to Blockly
Hi folks,

Nobody with a golden tip?  
Perhaps I could solve it another way, but again I'm stuck ...
  • When I open my Node-Red application, Node-Red handles all keydown events in it's flow editor.  I never arrive in the Blockly keydown handler.  This is perfect.
  • As soon as I open the Blockly popup, a new Blockly workspace is created (using Blockly.inject).  From here Blockly.onKeyDown_ handles all keydown event it the blockly editor.  This is perfect except that those events are ALSO handled by Node-Red (resulting in errors): but I could solve that by adding my own handler (as in my original question).
  • When I close the blockly popup, Node-Red should again handle all keydown events and Blockly should stop handling them.  Instead of replacing my own handler with the original Blockly handler (as in my original question) I just want Blockly to stop handling keydown events at all.  When the popup is closed I execute workspace.dispose(), however Blockly keeps handling to events.  So question is: how can I close the workspace, so it stops handling events?
Any advise is highly appreciated !!!!!

Thanks,
Bart

Mark Friedman

unread,
Jul 20, 2018, 7:00:24 PM7/20/18
to blo...@googlegroups.com
From https://github.com/google/blockly/blob/master/core/inject.js#L333, it looks like Blockly wants to maintain Blockly.onKeyDown_ across calls to Blockly.inject.  You might be able to explicitly reset Blockly.documentEventsBound_ and then use document.removeEventListener to remove the Blockly.onKeyDown_ handler.  It looks like the next call to Blockly.inject will then re-establish the Blockly.onKeyDown_ handler.  No guarantees, though, since I haven't tested this at all.  And, of course, this is all fooling around with private methods and properties, so it might not survive updates to Blockly.

-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+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Rachel Fenichel

unread,
Jul 20, 2018, 7:16:25 PM7/20/18
to Blockly
This is just a bug in Blockly: it's overly aggressive about key handling.  Hiding it doesn't make it stop.  Here's that bug filed in scratch-blocks: https://github.com/LLK/scratch-blocks/issues/1019

I tried to fix it earlier this year but other issues took priority.  We're happy to review pull requests to fix this bug.

Best,
Rachel
To unsubscribe from this group and stop receiving emails from it, send an email to blockly+u...@googlegroups.com.

Bart Butenaers

unread,
Jul 21, 2018, 8:01:58 AM7/21/18
to Blockly
Hi Mark, Rachel,

Thanks for all the provided links, which explained a lot of how it works.
I'm afraid I don't know enough yet about the internals of Blockly to create a pull request for this one.  Sorry ...
But now I could at least finally create a 'workaround' :
  • When opening the popup I run this code snippet:
            if (Blockly.blocklyEditorVisible === undefined) {
               
Blockly.originalKeyDownHandler = Blockly.onKeyDown_;
               
Blockly.onKeyDown_ = function(e) {
                   
// Stop the events from propagating up the DOM tree                  
                   
if (Blockly.blocklyEditorVisible) {
                       
Blockly.originalKeyDownHandler(e);
                        e
.stopPropagation();
                   
}
               
}
           
}
           
Blockly.blocklyEditorVisible = true;

So the custom onkeydown handler is setup ONCE , and from then on this handler will be used all the time by Blockly (i.e. I don't remove the handler anymore afterwards).  
  • When closing the popup I do this:
            Blockly.blocklyEditorVisible = false;

The custom handler works like this: when blocklyEditorVisible is true, I will call Blockly's original keydown handler (so the Blockly editor can handle keys) and don't pass the event up the DOM tree to Node-Red.   When blocklyEditorVisible is false, Blockly won't handle the event but the event goes up in the DOM tree where Node-Red will handle it.

Seems to be working all fine now, and no Node-Red errors anymore in my log.
The first version of my Node-Red contribution is ready to be published on NPM.

Thanks for all the time you have spend to my issue(s) !
Bart
Reply all
Reply to author
Forward
0 new messages