General XMetaL Discussion

XMetaL Community Forum General XMetaL Discussion How Do I Detect if a Node is Still in the Document?

  • scotth

    How Do I Detect if a Node is Still in the Document?

    Participants 5
    Replies 6
    Last Activity 11 years, 7 months ago

    Using XMetaL 6.0, I am sometimes saving references to nodes. When I delete one of those nodes and later try to perform an operation on the node whose reference I saved, I receive an error message stating that the node is no longer in the document. Currently, I am getting around this by using exception handling. However, I was wondering if there is a property or method that I can use to detect whether a node is still in the document.

    Reply

    Derek Read

    Reply to: How Do I Detect if a Node is Still in the Document?

    You can try ActiveDocument.ChangedNodes or ChangedNodesbyKey. Depending on how you have written your current scripts they may need to be rewritten to take advantage of this API. The Programmer's Guide topic for ChangedNodesbyKey has a usage example.

    Reply

    scotth

    Reply to: How Do I Detect if a Node is Still in the Document?

    What is the key referenced by ChangedNodesbyKey? In searching the help file, I am seeing a couple of methods that require this key as a parameter, but I cannot find an explanation of it anywhere. Is this an attribute that you can specify on a node?

    Reply

    Derek Read

    Reply to: How Do I Detect if a Node is Still in the Document?

    You don't have to use the key-savvy APIs, but the key allows you to track different changes.

    Here's something that might help you understand the feature. The script example for ChangedNodesbyKey in the Programmers Guide doesn't mention the first API I use here (but you need it unless you are using just ChangedNodes instead of ChangedNodesByKey).

    1. Open a document.

    2. Run the following script. This creates a key:
    [code]//XMetaL Script Language JScript:
    Application.AddChangedNodeKey(“key1”);[/code]

    3. Run the following script. You should be told that no changes have been made.
    [code]//XMetaL Script Language JScript:
    var mykey = “key1”;
    if (ActiveDocument.ViewType > 1) {
    ActiveDocument.ViewType=1;
    }
    var nds = ActiveDocument.ChangedNodesbyKey(mykey);
    var l = nds.length;
    var changenode = null;
    var name = null;
    var f = 0;
    ActiveDocument.Host.Alert(l);

    if (l==0){
    ActiveDocument.Host.Alert(“No nodes have been changed since the document was opened or the last time nodes were cleared.”);
    }
    else {
    for (var i=0; i<=l;i++){
    f++;
    changenode=nds.item(i);
    name = changenode.nodeName;
    ActiveDocument.Host.Alert(name
    + “nnNewNode:tt” + ActiveDocument.GetNodeStatebyKey(mykey, “NewNode”, changenode)
    + “nContentInserted:tt” + ActiveDocument.GetNodeStatebyKey(mykey, “ContentInserted”, changenode)
    + “nContentDeleted:tt” + ActiveDocument.GetNodeStatebyKey(mykey, “ContentDeleted”, changenode)
    + “nAttributesChanged:tt” + ActiveDocument.GetNodeStatebyKey(mykey, “AttributesChanged”, changenode));
    if (f==nds.length){
    break;
    }
    }
    }[/code]

    4. Make one of the following changes to the document: Type some text, insert an element, delete an element, change an attribute.

    5. Run the script from step 3 again. This time it will report details on what changed.

    6. Repeat steps 4 and 5 until you figure out how this stuff works (it can be complex).

    7. Add other macros that make (separate) calls to the following and test various combinations:
      a) Application.RemoveChangedNodeKey(mykey);
      b) ActiveDocument.ClearAllChangedStatesbyKey(mykey);
      c) ActiveDocument.ClearNodeChangedStates(mykey, changenode, true);
      d) ActiveDocument.ClearNodeChangedStatesbyKey(mykey,changenode,false);

    If you don't want to deal with keys (I would recommend that unless there is a real need to keep track of separate types of changes for some reason) then you can just the non-key version of the same APIs. In this case you don't need step 2:

    [code]// XMetaL Script Language JScript:
    if (ActiveDocument.ViewType > 1) {
    ActiveDocument.ViewType=1;
    }
    var chgdNodes = ActiveDocument.ChangedNodes;
    var msg = “Changed nodes: ” + chgdNodes.length;
    for (i=0;i changenode=chgdNodes.item(i);
    msg += “n—————————————-n”;
    msg += changenode.nodeName;
    msg += “nNewNode:tt” + ActiveDocument.GetNodeState(“NewNode”, changenode);
    msg += “nContentInserted:tt” + ActiveDocument.GetNodeState(“ContentInserted”, changenode);
    msg += “nContentDeleted:tt” + ActiveDocument.GetNodeState(“ContentDeleted”, changenode);
    msg += “nAttributesChanged:tt” + ActiveDocument.GetNodeState(“AttributesChanged”, changenode);
    }
    Application.Alert(msg);[/code]

    Step 7 will be different as well as you will need to use the non-key version of those APIs.

    Reply

    scotth

    Reply to: How Do I Detect if a Node is Still in the Document?

    Thanks for the example. I must admit that it's not clear to me what the advantage of the key is. Is it simply a matter of being able to track changes over a given period of time? For example, let's say that you know you are going to perform a sequence of changes that you would like to be able to track. You set the key, make the changes, and then remove the key. After removing the key, you are still able to review the changes made while that key was in effect by calling GetNodeStatebyKey and using the old key. However, any new changes will not be associated with that key, since it has been removed. Am I on the right track here?

    Reply

    Derek Read

    Reply to: How Do I Detect if a Node is Still in the Document?

    That's sort of it. We originally added the non-keyed versions and then (long ago) realized that different integrations and customizations could (and would) step on each other if they were running at the same time. So we added the keyed versions with the intention being to allow developers to avoid these types of conflicts.

    When a document is opened ChangedNodes should be zero length. As you change things the ChangedNodes list grows. If you want to reset it you call one of the “Clear*” methods. However, if multiple integrations (with 3rd party software) or customizations (either application-level for Author or document-level for Author and XMAX) use non-keyed version of ChangedNodes and any of them calls one of the “Clear*” methods then that would break one of the others.

    When you set a key it associates the document's ChangedNodes with that particular key. This allows you to use the “Clear*” APIs to clear the list associated with that key without affecting any others associated with other keys.

    If you are running XMAX (I believe that is the case) you might not need to worry about the key as everything is usually under your control.

    XMetaL Author Enterprise is perhaps more frequently integrated with various 3rd party software and customizations, though XMetaL Author Essential can be as well. In particular, we  promote the use of XMetaL Author Enterprise for use with CMS systems (because it has a special set of APIs for use specifically with them and Essential does not). XMetaL Reviewer uses the key version of these APIs and other 3rd party software may do as well. Any of these might use a ChangedNodes list and in order to not break the list that others are using they will use the key version.

    In theory you might use this for other purposes but we have not done any extensive testing along those lines.

    Reply

    Derek Read

    Reply to: How Do I Detect if a Node is Still in the Document?

    Actually, if you are running XMAX you cannot use the key versions because it is lacking the Application object and the method for adding a key is Application.AddChangedNodeKey().

    Reply

  • You must be logged in to reply to this topic.

Lost Your Password?

Products
Downloads
Support