General XMetaL Discussion
XMetaL Community Forum › General XMetaL Discussion › Get nodelist from Selection/Range?
-
schwamkrug September 11, 2012 at 4:50 pm
Get nodelist from Selection/Range?
September 11, 2012 at 4:50 pmParticipants 10Replies 11Last Activity 10 years, 4 months agoI 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 itSo, 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.
Derek Read September 12, 2012 at 4:26 pm
Reply to: Get nodelist from Selection/Range?
September 12, 2012 at 4:26 pmDoes 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.schwamkrug September 12, 2012 at 4:36 pm
Reply to: Get nodelist from Selection/Range?
September 12, 2012 at 4:36 pmI 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.Derek Read September 12, 2012 at 6:02 pm
Reply to: Get nodelist from Selection/Range?
September 12, 2012 at 6:02 pmWhat do you need to do with these nodes once you have them?
Perhaps knowing that will help me provide a better answer.schwamkrug September 12, 2012 at 6:19 pm
Reply to: Get nodelist from Selection/Range?
September 12, 2012 at 6:19 pmSure. 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 elementsincluded 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 elementsincluded Or this:
someinline elementsincluded 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.
Derek Read September 12, 2012 at 8:05 pm
Reply to: Get nodelist from Selection/Range?
September 12, 2012 at 8:05 pmSo this is actually modifying the DITA authoring functionality in XMetaL Author Enterprise?
schwamkrug September 12, 2012 at 9:00 pm
Reply to: Get nodelist from Selection/Range?
September 12, 2012 at 9:00 pmI 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.
Derek Read September 12, 2012 at 9:14 pm
Reply to: Get nodelist from Selection/Range?
September 12, 2012 at 9:14 pmThis 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;imsg += nodes.nodeName + “n”;
}
Application.Alert(msg);[/code]schwamkrug September 12, 2012 at 9:38 pm
Reply to: Get nodelist from Selection/Range?
September 12, 2012 at 9:38 pmThanks, 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?
Derek Read September 12, 2012 at 11:17 pm
Reply to: Get nodelist from Selection/Range?
September 12, 2012 at 11:17 pmIf 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.
Derek Read September 12, 2012 at 11:21 pm
Reply to: Get nodelist from Selection/Range?
September 12, 2012 at 11:21 pm“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.
schwamkrug September 13, 2012 at 3:02 am
Reply to: Get nodelist from Selection/Range?
September 13, 2012 at 3:02 amAwesome, 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] -
AuthorPosts
- You must be logged in to reply to this topic.