On this Page

    Debugging Script

    DocOrigin Merge provides a number of options and functions to assist in debugging scripts:

    • the -trace command line option.

    This causes the program to write a detailed trace log of its execution steps as the script is being executed. Note that the trace file is overwritten on each run (whereas the log file is appended to). Use this command option as follows:

    ... -trace "C:/DocOrigin/User/test/trace.log" ...

    This can be used within your script to write information directly to the trace file specified in the -trace command line option. If -trace is not specified it does nothing. Well, not quite nothing. If you are tracing out values that require work to create (a favorite is ._fullName, which is fairly expensive to come up with) then that effort/time will be expended even though no trace output will be generated. As of 3.1.002.03, you can use conditional commenting, by prefacing the _tracef line with !!, to fully remove any processing costs.

    • the _message function call (Windows only).

    This is a variation of the _message function that will display a message as a Windows popup message box. It has effect only when the -debug command-line option has been specified. That means that you can leave it in during production (where -debug is not set!). Well, see the conditional commenting remarks above. That applies here too. By the way, there is a _dlogf() function as well. Log output occurs only when -debug is specified.

    For example:

     _dmessage("my var='%s'", myvar); // display myvar

    Techniques

    See all Command-Line Options

    Sometimes you just want to know what the command line options were and any other information that has been provided to your script. The following is a fine way to see everything in _job.

    if (typeof _job != "undefined") {
    	for (var prop in _job)
    		_logf("_job.%s = '%s'\n", prop, _job[prop]);
    	if (typeof _job.command != "undefined")
    		for (var prop in _job.command)
    		_logf("_job.command.%s = '%s'\n", prop, _job.command[prop]);
    	if (typeof _job.options != "undefined")
    		for (var prop in _job.options)
    		_logf("_job.options.%s = '%s'\n", prop, _job.options[prop]);
    	if (typeof _job.filter != "undefined")
    		for (var prop in _job.filter)
    		_logf("_job.filter.%s = '%s'\n", prop, _job.filter[prop]);
    } 

    In general, it is good to become friends with the standard JavaScript features of:

    typeof variable

    and     for (var prop in object) ... object[prop]

    Note: As of 3.1.001.24 the function _job.logf(["context string"]) was added to all of the above logging of the _job object. The context string is optional. It simply helps to identify where in the script you are dumping out this info.

    Also in 3.1.001.24, a similar function, _cache.logf(["context string"]) was introduced to easily log all the _cache settings defined at the time of the call.

    You cannot use for (var prop in domObject). The performance penalty to support that would be far too great. You have to know the property names of those dynamic DOM objects.

    Traverse the DOM

    Well, suppose you just want to know your whole world, perhaps wanting to see what the names really are as opposed to what you think is out there:

    _logf("\n%E -- The entire document DOM..\n");
    for (var r=_document; r; r=r._nextNode) {
        _logf("..  '%s'\n", r._fullName);
    }
    _logf("\n\n");

    It's a great habit to put single quotes around strings that you are debugging. You might be surprised how often there is a trailing (or leading) character that you did not expect.

    Of course, you can traverse other DOMs than the _document DOM, e.g. the _data dom, or an individual page's _page DOM. And you can start at some level other than the root of the DOM.

    Sometimes you may be surprised by what doesn't show up. A bit of reflection can then lead to an 'Ahah' moment.

    Note the use of _fullName. It's a wonderful thing.

    What pages do I have

    At Pagination Completed time it is often desirable just to 'traverse' through all the pages. This can be true at Data Merged time too, but less often, in my experience.

    _logf("\n%E -- All my pages..\n");
    for (var pg=_document._firstChild; pg; pg=pg._nextSibling) {
    	_logf("..  '%s'\n", pg._fullName);
    }
    _logf("\n\n");

    The trick here is that page objects are always the immediate children of the top-level _document object. That makes the above loop far faster than using the entire _nextNode loop depicted farther up.

    Naturally, you might want to look at more than the names of the pages, and you might want to predicate your logging with whether pg._visible is true. It's all available at your property's fingertips.

    Note that %E is a special format specifier. It requires no parameter. It reports the name of the event that this script is in, e.g. "Data Merged" or "Pagination Completed". Use it. It might tweak you to the fact that you put your script in the wrong event.

    What panes do I have

    Suppose you are on a page object and you want to know what panes have been instantiated for this page [instance]. You could use:

    _logf("\n%E -- All panes of '%s'..\n", this._fullName);
    for (var pn=this._firstChild; pn; pn=pn._nextNode) {
    	if (pn._type == "Pane")
    		_logf("..  '%s'\n", pn._fullName);
    	if (pn._type == "Page") break;
    }

    Because panes can be nested, you can't use just _nextSibling. Instead, use _nextNode. But now you have way too many nodes. Use the _type property to select only the type of object that you want. It happens that you will be surprised at all the instances that it reports, or perhaps more so, doesn't report. It's very helpful to know these things.

    See Also

    -phase
    _cache (Scripting Object)