• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

Debugging callback functions

Community Expert ,
Apr 27, 2016 Apr 27, 2016

Copy link to clipboard

Copied

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.

TOPICS
Scripting

Views

1.2K

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

Enthusiast , Apr 29, 2016 Apr 29, 2016

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!!!!!!

Votes

Translate

Translate
Community Expert ,
Apr 27, 2016 Apr 27, 2016

Copy link to clipboard

Copied

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.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Apr 27, 2016 Apr 27, 2016

Copy link to clipboard

Copied

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.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Apr 28, 2016 Apr 28, 2016

Copy link to clipboard

Copied

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.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Mentor ,
Apr 28, 2016 Apr 28, 2016

Copy link to clipboard

Copied

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

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Apr 28, 2016 Apr 28, 2016

Copy link to clipboard

Copied

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

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Apr 28, 2016 Apr 28, 2016

Copy link to clipboard

Copied

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.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Apr 28, 2016 Apr 28, 2016

Copy link to clipboard

Copied

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.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Apr 29, 2016 Apr 29, 2016

Copy link to clipboard

Copied

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.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Apr 29, 2016 Apr 29, 2016

Copy link to clipboard

Copied

Which FrameMaker version do you use?

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Apr 29, 2016 Apr 29, 2016

Copy link to clipboard

Copied

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

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Apr 29, 2016 Apr 29, 2016

Copy link to clipboard

Copied

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!!!!!!

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Apr 29, 2016 Apr 29, 2016

Copy link to clipboard

Copied

LATEST

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

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines