General XMetaL Discussion

XMetaL Community Forum General XMetaL Discussion Get nodelist from Selection/Range?

  • schwamkrug

    Get nodelist from Selection/Range?

    Participants 10
    Replies 11
    Last Activity 10 years ago

    I feel like I'm missing something obvious, but is there an API call to get a node list/array from a selction? Something along these lines:

    var rng = Application.ActiveDocument.Range;
    var nodeList = rng.GetNodeList();
    //iterate over the nodeList and do things with it

    So, if I select a couple of

    elements, that nodeList would have DOMNodes for those p tags? Of course, that doesn't quite make sense if I've selected part of a text node.

    Reply

    Derek Read

    Reply to: Get nodelist from Selection/Range?

    Does getNodesByXPath() help you here? That is the first thing I can think of that requires the least amount of code.
    The DOMElement object has this as a method. You can use Selection.ContainerNode to get the node for the current selection's immediate parent.

    Reply

    schwamkrug

    Reply to: Get nodelist from Selection/Range?

    I don't think that would help because it wouldn't give me the ability to see which specific nodes are selected. Imagine this chunk of content:


     

    Paragraph 1

     

    Paragraph 2

     

    Paragraph 3

     

    Paragraph 4

     

    Paragraph 5

    And assume I have paragraph 2 and paragraph 3 selected. Selection.ContainerNode returns the element. I don't see how I could use XPath to get the two specific paragraphs that are selected.

    Reply

    Derek Read

    Reply to: Get nodelist from Selection/Range?

    What do you need to do with these nodes once you have them?
    Perhaps knowing that will help me provide a better answer.

    Reply

    schwamkrug

    Reply to: Get nodelist from Selection/Range?

    Sure. I'm working on a macro to enable cutting/pasting content as a conref. It was pretty easy to do this with a single element…with the cursor inside a given element, get Selection.ContainerNode, then do typical DOM stuff to add a conref to the clipboard. But what I want to do is extend that to also do conref range. Consider the following (assume all these elements have ids):


     

    Paragraph 1, with some inline elements included in them.

     

    Paragraph 2

     

    Paragraph 3

     

    Paragraph 4

     

    Paragraph 5

    If the following is selected:
     

    Paragraph 2

     

    Paragraph 3

     

    Paragraph 4

    I'd use the id from Paragraph 2 for the conref attribute, and the id from paragraph 4 for the conrefend attribute.

    However, if I selected this:
      inline elements includedOr this:
        some inline elements included in them.

    Those would be error conditions. Those wouldn't be the only error conditions. The main thing is that I'd need to get a node list and look at it to see.

    Reply

    Derek Read

    Reply to: Get nodelist from Selection/Range?

    So this is actually modifying the DITA authoring functionality in XMetaL Author Enterprise?

    Reply

    schwamkrug

    Reply to: Get nodelist from Selection/Range?

    I guess it depends on what you mean by modifying… I'm just adding a macro to fill the clipboard with a conref. It's written as an application macro, so it's not really aware of whether it's in a DITA doc or not. It just looks for elements with id attributes.  I'm not looking to hook into or override any of the functionality you guys provide.

    Reply

    Derek Read

    Reply to: Get nodelist from Selection/Range?

    This is very likely incomplete but you might build on it. There are probably test cases I have not thought of.
    If you want to capture other types of nodes (text, comment, PI, etc) then this would probably need to be substantially rewritten.

    [code]//XMetaL Script Language JScript:
    //debugger;
    var nodes = Array();
    var rngS = ActiveDocument.Range;
    var rngE = rngS.Duplicate;
    rngS.Collapse(sqCollapseStart);
    rngE.Collapse(sqCollapseEnd);
    var i = 0;
    rngS.MoveToElement();
    while(rngS.IsLessThan(rngE,false)) {
    if(rngS.ContainerNode.nodeType == 1) {
    nodes = rngS.ContainerNode;
    i++;
    }
    if(rngS.MoveToElement() == false) {
    break;
    }
    }

    var msg = “”;
    for(i=0;i msg += nodes
    .nodeName + “n”;
    }
    Application.Alert(msg);[/code]

    Reply

    schwamkrug

    Reply to: Get nodelist from Selection/Range?

    Thanks, Derek. That helps a lot.

    Slight change of subject…is there a way to reload .mcr files without restarting XMetaL so I can test changes to my code?

    Reply

    Derek Read

    Reply to: Get nodelist from Selection/Range?

    If you have XMetaL Developer installed then you can use Visual Studio's “edit and continue” feature though in some cases that is impossible (depends on the changes you have made to your script). Microsoft doesn't seem to document this feature for scripting languages that use WSH but this comes close: http://msdn.microsoft.com/en-us/library/ba77s56w%28v=vs.80%29.aspx

    If you don't have XMetaL Developer then calling the API Application.RefreshMacros() will do what you want, depending on which events the macros are in. Some events will still require a restart because they just won't fire any longer (mostly events that fire at application start up obviously). By default there is a macro included that calls that API (it is in xmetal.mcr) and pressing Ctrl+Alt+R will run it.

    Reply

    Derek Read

    Reply to: Get nodelist from Selection/Range?

    “Edit and continue” in Visual Studio is described well here: http://www.codeproject.com/Articles/359801/10plus-powerful-debugging-tricks-with-Visual-Studi

    Most of the other features work as described for JScript / VBScript as well.

    Reply

    schwamkrug

    Reply to: Get nodelist from Selection/Range?

    Awesome, thanks.

    So, I think an easier answer just slapped me across the face:

    [code]
    var rng = Application.ActiveDocument.Range;
    var selectionXMLString = ““+rng.Text+”“;
    var xmlDoc = new ActiveXObject(“msxml2.DOMDocument”);
    xmlDoc.loadXML(selectionXMLString);
    var nodes = xmlDoc.documentElement.childNodes;
    [/code]

    Reply

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

Lost Your Password?

Products
Downloads
Support