12 Replies Latest reply on Apr 29, 2016 11:16 AM by K.Daube

    Debugging callback functions

    K.Daube Level 1

      Am I right with my observations?

      Ordinary (not named) callback functions are all listed as (for example) onClick() in the Functions pane of ESTK. In addition local variables in these functions are not listed in the Data Browser. Hence IMHO debugging is not possible.

      So I tried the method with named callback functions which avoids both drawbacks:

      Unnamed callback functionsNamed callback functions
      myDlg.btn2.onClick = function() {
        $.bp(true);
        aLocal = "gugus";
        if (this.text == 'Disable Him') {
          this.text = 'Enable Him';
          myDlg.btn1.enabled = false;
        } else {
          this.text = 'Disable Him';
          myDlg.btn1.enabled = true;
        }
      }
      myDlg.btn2.onClick = ActButton2;
      // ...
      function ActButton2 () {
      $.bp (true);
        var aLocal = "gugus";
        if (this.text == 'Disable Him') {
          this.text = 'Enable Him';
          myDlg.btn1.enabled = false;
        } else {
          this.text = 'Disable Him';
          myDlg.btn1.enabled = true;
        }
      }
      variable aLocal is not listed in Data Browservariable aLocal is listed in Data Browser
      All functions are named onClick in the Functions paneFunctions have distinct names in the Functions pane
      callback functions are within the window functioncallback functions (are) / (may be) outside the window function

       

      Of course the names for the named callback functions must be unique for the whole script.

        • 1. Re: Debugging callback functions
          K.Daube Level 1

          I fell into the trap of a working simple example - in real life aka my long script) it does not work:

          The named fallback functions are entered even during creation of the diaglog/palette - and not only on a click on the buttons. Hence they are entered before the dialouge is really set up and visible...

          The sekeleton of my dialog routine is this:

           

          function PaletteCalcMarkers(){
          var gsMarkerName= "#calc";
          var indexOfMarker = RefreshGlobalsC ();          // if null => inactivatemost buttonsuff
          var palC = new Window('palette',"Handle #Calc Markers",undefined);  // dialog or palette
              palC.p0 = palC.add('panel',undefined,undefined);// outmost panel
          // -- lot of stuff
          // --- behaviour of the buttons====================================================================
              palC.p0.g2.btnInsert.onClick =  ButtonInsertC (palC);
          // -- more of these (one for each button)
              palC.p0.g4.Cancel.onClick = function () { // the only unname one i left
                palC.close();
              }
            if (indexOfMarker === null) HideButtonsC(palC);
            palC.show();
          } // end of PaletteCalcMarkers --------------------------------------------------------------------
          
          function ButtonInsertC (palC) {
            indexOfMarker = InsertMarker (goCurrentDoc.TextSelection, gsMarkerName, gsMarkerText)
            goCurrentMarker = goaCalcMarkers[indexOfMarker];
            DisplayMarker (goCurrentDoc, goCurrentMarker);
            palC.p0.sMarkerContent.text ="";
            gsMarkerText = goCurrentMarker.MarkerText;
            palC.p0.sMarkerContent.textselection = gsMarkerText;
          }
          // -- More of these functions (one for each button)
          

           

          So I'm back to square one with not being able to check local variables in the unnamed fallback functions.

          • 2. Re: Debugging callback functions
            Klaus Göbel Level 3

            Hello Klaus,

             

            I don't know the answer (yet).

            But  I can give you one hint:

             

            I read somewhere(???) that a "Window" MUST be defined globally (outside the function).

             

            I don't know, if this could solve your problem.

            So just try it.

            • 3. Re: Debugging callback functions
              K.Daube Level 1

              Klaus, this has no influence on the behaviour.

              I have set up a simpler example with both cases: internal callback functions and external (named) ones.

              While the transfer of parameters works they can not be inspected in the Data Browser - the theme of this thread.

              /* NamedCallbackFunctions.jsx
                 Call back functions defined within the dialog function work as intended
                 Named (externalised) dialog function doe not work correctly
              */
              
              var globalValue = 17;
              var wPnl  = new Window ("dialog", "Paneled Dialog OK", undefined);
              var wPnlN = new Window ("dialog", "Paneled Dialog NOK", undefined);
              
              PaneledDialog    (globalValue);     // callback functions run before dialog is visible
              alert ("Now the demonstration of the named callback functions");
              PaneledDialogNOK (globalValue);     // this is OK
              
              /* Callback functions defined and invoked inside the dialogue fucntion work as intended
                 It is, however, not possible to transfer local parameters to them
                 The setup of the windows does'nt need to be outside the dialogue function
                 (as suggested by Klaus Göbel)
              */
              function PaneledDialog (outerParm) {
                var innerParm = 19;
                var whatIsThis = 99;
                wPnl.p0    = wPnl.add ("panel", undefined, "a panel");
                wPnl.p0.b1 = wPnl.p0.add ("button", undefined, "Outer");
                wPnl.p0.b2 = wPnl.p0.add ("button", undefined, "Inner");
                wPnl.p0.st = wPnl.p0.add ("statictext", undefined, "st= " + innerParm); // initially 19
              
                wPnl.p0.b1.onClick = function () {
                  alert ("Outer argument outerParm is " + outerParm, "PaneledDialog OK", false); // = 17
                  alert ("whatIsThis is " + whatIsThis, "PaneledDialog OK", false);              // undefined
                }
                wPnl.p0.b2.onClick = function Button2P () {
                  alert ("Inner argument innerParm is " + innerParm, "PaneledDialog OK", false); // = 19
                  wPnl.p0.st.text = "st= 13";                   // this changes the display
                }
                wPnl.show ();
              }
              
              /* Externalised named callback functions - probaly misunderstood from
                 javascript Tools Guide > Defining event-handler callback functions
                 This does not work: the callback functions are invoked during buildup of the dialog
                 even before the dialogue becomes visible.
                 The setup of the windows does'nt need to be outside the dialogue function
                 (as suggested by Klaus Göbel)
              */
              function PaneledDialogNOK (outerParm) {
                var innerParm = 19;
                var whatIsThis = 99;
                wPnlN.p0    = wPnlN.add ("panel", undefined, "a panel");
                wPnlN.p0.b1 = wPnlN.p0.add ("button", undefined, "Outer");
                wPnlN.p0.b2 = wPnlN.p0.add ("button", undefined, "Inner");
                wPnlN.p0.st = wPnlN.p0.add ("statictext", undefined, "st= " + innerParm); // initially 19
              
                wPnlN.p0.b1.onClick = Button1p (whatIsThis, outerParm) ;
                wPnlN.p0.b2.onClick = Button2P (innerParm);
              
                wPnlN.show ();
              }
              
              function Button1p (whatIsThis, outerParm) {
                  alert ("Outer argument outerParm is " + outerParm, "PaneledDialog NOK", false); // = 17
                  alert ("whatIsThis is " + whatIsThis, "PaneledDialog NOK", false);              // = 99
                }
              function Button2P (innerParm) {
                alert ("Inner argument innerParm is " + innerParm, "PaneledDialog NOK", false);   // = 19
                wPnlN.p0.st.text = "st= 13";                    // this changes the display
              }
              

              Setting a breakpoint with $.bp(true); - for example after line 27 - works only if

              #target framemaker

              is present.

              • 4. Re: Debugging callback functions
                Russ Ward Level 4

                Hi Klaus D.,

                 

                Two thoughts, neither are very deep...

                 

                - I've seen variables fail to appear in the Data Browser if they simply lacked "var" in the declaration, like "var myVar = "Hi Klaus". Your original post shows this. While JavaScript doesn't care, the Data Browser sometimes seems to.

                 

                - In general, I've found the Data Browser and debug tools to have bad moods and just act strange sometimes.

                 

                Russ

                • 5. Re: Debugging callback functions
                  cudspan Level 1

                  Wait a minute...  Does the variable even exist before the callback is called?  I get confused by closure and life cycle in javascript...

                  • 6. Re: Debugging callback functions
                    K.Daube Level 1

                    Hi Russ,

                    The DataBrowser does not show any local variables from a callback function - independently of they are really declared locally to that function by var ... or that they are global (that is declared in the window setup function).

                    And yes, the behaviour is sometimes erratic and I just close everything (FM, ESTK) and start afresh.

                     

                    CudSpan,

                    When using the 'named callback functions" I need to call the real functions (which are outside the scope of the window function) with parameters to get some values into them. See lines 53 and 54 above. If i just use

                    wPnlN.p0.b1.onClick = Button1p;  
                    wPnlN.p0.b2.onClick = Button2P;
                    

                    as it is describe in the Javascript Tools Guide > Defining event-handler callback functions, then of course all varirables are undefined in the external functions.

                    So, IMHO named callback functions either work completely differt than I can deduct from the documentation - or this is a dead end anyway.

                    I have resorted back to the unnamed method of doing it and need lots of alerts in the functions to know what's going on - thanks a very helpless Data Browser.

                    • 7. Re: Debugging callback functions
                      Klaus Göbel Level 3

                      Hi Klaus,

                       

                      I've tested your script several times and for me it works!

                       

                      I'm using FM 2015 with the new update 3.1 (from today)

                       

                      I'm gonna test it now with FM12.

                      • 8. Re: Debugging callback functions
                        K.Daube Level 1

                        Klaus, in my tests,

                        As soon as I execute line 12 containing

                        PaneledDialogNOK (globalValue);     // this is ot OK

                        the external callback routines are run and all alerts happen. Only after that the dialog is displayed and the buttons don't work.

                        • 9. Re: Debugging callback functions
                          Klaus Göbel Level 3

                          Which FrameMaker version do you use?

                          • 10. Re: Debugging callback functions
                            K.Daube Level 1

                            Klaus, I did the tests with FM-12.0.2.433 and just now again with FM-13.0.3.495 (13.0.3.1)

                            => Same behaviour: As soon as I execute line 12 containing

                            PaneledDialogNOK (globalValue);
                            

                            the external callback routines are run and all alerts happen. Only after that the dialog is displayed and the buttons don't work.


                            Please note that in the posted script the comments are exchanged. Lines 10 - 12 shoul read

                            PaneledDialog    (globalValue);    // this is OK
                            alert ("Now the demonstration of the named callback functions");
                            PaneledDialogNOK (globalValue);    // callback functions run before dialog is visible
                            
                            • 11. Re: Debugging callback functions
                              Klaus Göbel Level 3

                              Which FrameMaker version do you use?

                               

                              Now I see your problem:

                               

                              You can't do something like this:

                              wPnlN.p0.b1.onClick = Button1p (whatIsThis, outerParm) ;  
                              

                               

                              Means: you can't pass parameters to this function here. Otherwise the function is executed immediately.

                               

                              wPnlN.p0.b1.onClick = Button1p; // no brackets!!!!!!
                              
                              • 12. Re: Debugging callback functions
                                K.Daube Level 1

                                Thanks Klaus - I think the behaviour is now demystified:

                                • External named callback functions can be identified in the functions pane of ESTK
                                • Variables local to these functions are visible in the Data Browser
                                • $.bp (...) requires #target framemaker
                                • To get access to variables defined in the dialog function the window declaration must be outside the dialog function (and of course define a name) - line 5.

                                 

                                // argumentsInNamedCallbackFunction2.jsx
                                #target framemaker
                                
                                var globalValue = 17;
                                var wPnlN = new Window ("dialog", "Paneled Dialog NOK", undefined);
                                
                                PaneledDialog (globalValue);
                                
                                function PaneledDialog (outerParm) {
                                  var innerParm = 19;
                                  var whatIsThis = 99;
                                  wPnlN.p0    = wPnlN.add ("panel", undefined, "a panel");
                                  wPnlN.p0.b1 = wPnlN.p0.add ("button", undefined, "Outer");
                                  wPnlN.p0.b2 = wPnlN.p0.add ("button", undefined, "Inner");
                                  wPnlN.p0.st = wPnlN.p0.add ("statictext", undefined, "st= " + innerParm); // initially 19
                                
                                  wPnlN.p0.b1.onClick = buttonOuter;                 // there must not be parameters!
                                  wPnlN.p0.b2.onClick = buttonInner;                 // or the functions are executed immediately
                                
                                  wPnlN.show ();
                                }
                                
                                function buttonOuter () {
                                $.bp(true);
                                var whatIsThis = "local to buttonOuter";          // visible in Data Browser
                                    alert ("Outer argument outerParm is: " + wPnlN.outerParm); // = 17 not visible in DB
                                    alert ("whatIsThis is " + whatIsThis);
                                  }
                                function buttonInner () {
                                $.bp(true);
                                  alert ("Inner argument innerParm is: " + wPnlN.innerParm);
                                  wPnlN.p0.st.text = "st= 13";                  // this changes the display
                                }
                                

                                 

                                Thnak You all for this discussion and solution.

                                Klaus