No internet connection
  1. Home
  2. Support

Unexpected "Cancel" button behavior

By Chris Shaw @Chris_Shaw2020-07-11 21:34:15.424Z2020-07-11 21:40:27.654Z

I'm using this piece of code in my Move Tracks script (I've modified it slightly here for demo purposes).

sf.ui.proTools.appActivate();


let selectDestinationTrack = (sf.interaction.displayDialog({
    prompt: "Select a destination track and click OK.\n \n(Your tracks will be moved below this track)",
    defaultButton: "OK",
    buttons: ["Top of Session", "OK", 'Cancel'],
    //cancelButton: "Cancel",
})).button;

if (selectDestinationTrack == 'Top of Session') {
    alert("You selected Top")

} if (selectDestinationTrack == "OK") {
    alert("You selected a destination track")

} if (selectDestinationTrack == 'Cancel') {
    alert("I'm quitting Now!")
    throw 0;
} 

I've noticed that the last if doesn't execute when the user cancels. It seems that just labeling a button "Cancel" makes it cancel execution even if you don't use the cancelButton: "Cancel" argument as shown above.

The only way I can get the Cancel button to behave the way I want (alert("I'm quitting Now!")is to add a trailing space after the word Cancel like so:

buttons: ["Top of Session", "OK", 'Cancel '] 

Is this the expected behavior?

  • 20 replies

There are 20 replies. Estimated reading time: 6 minutes

  1. Hi Chris,

    I think you need to add the property onCancel: 'Continue' to the displayDialog call if you want a Cancel click to not stop your script.

    1. By default SoundFlow (and the user) expects that clicking Cancel on a dialog means the user didn't want to do the thing they started anyway. So that's why the default behavior clicking Cancel is to stop the script (akin to throw 0).

      1. In your case, I don't agree with the logic you're setting up that you should display an alert box after the user has clicked Cancel. That's not typically how clicking Cancel works across normal user interfaces. Normally, clicking Cancel just silently stops the current operation.

        1. I'm just throwing an alert box in the above script as an example piece of code. I probably should have used log instead. Sorry for the confusion.

          1. When I debug my scripts I use alerts as a way to pause the script and display variables/strings.

            1. Makes perfect sense. But I'd still argue in 99% of cases you wouldn't need to handle the behavior yourself after the user has pressed cancel so you could just leave the default behavior as is. Running code after the user has clicked cancel would typically not be what the user expects.

              1. My move tracks scripts creates a show hide memory location to restore the tracks view the user had before executing the script. The the script then displays/unhides all tracks before asking the user for the destination track.

                My goal is recall this memory location and then delete it if the user cancels. Hence my need to execute a couple of lines of code before quitting the script.

                1. Gotcha :) One of the 1% haha.

                  I would consider doing this with a try / finally block instead though, as that would also ensure your cleanup code is run in any other exceptional cases (if an error happens during the normal run of events)

                  1. hmm, Try / Finally - off to JavaScript school 😄

                    1. Sorry for the brevity, I was typing most of this on my phone.

                      The general concept of try/finally is that whatever happens inside the try block, the finally block will ALWAYS be called.
                      This includes if an exception happens inside the try block, (including a throw 0), and even if you just call return inside the try block - the finally block will ALWAYS be executed.

                      So in your case, instead of trying to overwrite the cancel behavior, I would do:

                      try {
                          //Call the function here that may or may not cancel out early.
                          //In fact, any code from the moment you do something that needs cleanup until you're done with the whole stuff, should go in your try block
                      } finally {
                          //Do the cleanup here
                      }
                      
                      1. So for example, in all these cases the alert should show.

                        try {
                            throw 0;
                        } finally {
                            alert('Cleanup');
                        }
                        
                        try {
                            //Click cancel and check that Cleanup is still called
                            let selectDestinationTrack = (sf.interaction.displayDialog({
                                prompt: "Select a destination track and click OK.\n \n(Your tracks will be moved below this track)",
                                defaultButton: "OK",
                                buttons: ["Top of Session", "OK", 'Cancel'],
                            })).button;
                        } finally {
                            alert('Cleanup');
                        }
                        
                        1. Note since the finally block is ALWAYS called, this includes of course the regular case where everything goes well inside the try block and no exceptions or return statements are called.

                          1. Another example where the finally block should be called:

                            function testFunction() {
                                try {
                                    return true;
                                } finally {
                                    alert('Cleanup');
                                }
                            }
                            
                            testFunction();
                            
                            1. More info on try-catch, try-catch-finally and try-finally blocks here:
                              https://javascript.info/try-catch

                              1. Thanks for all the info Christian. I read up on this yesterday but seeing it in context of the code I wrote helps immensely…

      2. In reply tochrscheuer⬆:

        I see that onCancel: 'Continue' returns null as well.
        Good to know

      3. In reply toChris_Shaw⬆:

        In other words, It seem that SF or JavaScript automatically binds a stop execution command to any button that is labeled ""Cancel".

        1. Correct.

          1. Unless you add an onCancel: 'Continue' property as stated previously.

        2. In reply toChris_Shaw⬆:

          Thanks for clarifying Christian!