Home Forums General XMetaL Discussion Finding and returning exact insert location Reply To: Finding and returning exact insert location

Derek Read

Reply to: Finding and returning exact insert location

When you call FindInsertLocation() it actually moves the Selection (or Range if you are using Range) to the next valid position where the specified element is allowed to be inserted, so there is nothing more to find or move. The selection is already there.

However, it sounds like you are mixing the use of DOM and Selection/Range? That complicates things a bit as these are different concepts (and modelled differently inside XMetaL and require the use of APIs on different objects). There are APIs to “convert” from one to the other but how you mix the two (and even if you can do it) depends on what you are doing.

After calling FindInsertLocation() your Selection is exactly where you indicate in your example. So, if you wish to use that as the insertion point but then use a DOM call to do the insertion you will need to convert the Selection into a DOM node using Selection.ContainerNode. Once you have that node you can call insertBefore() or appendChild().

Unfortunately the node your selection is inside of is . So, calling insertBefore() will end up trying to put your copied node before . That is not what you want. Calling appendChild() will try to add your copied node to the end of and that is not what you want either.

To use these DOM calls for insertion I think you would need to somehow find and then call insertBefore(), or move the selection using Selection.MoveRight(), Selection.GotoNext(), or maybe even Selection.MoveToElement(“node3”), after your call to FindInsertLocation(). However, that doesn't seem very robust to me.

Have a look at the code example in the Programmers Guide for “createDocumentFragment”. I think it is a good example for mixing DOM and the Selection / Range objects.

It might be far simpler to not use DOM at all. Instead of using clodeNode() earlier on in your script to copy the element you would start right from the beginning by moving the Selection around (better to use Range in most cases actually as it can get to more places than a regular user can, and it is generally invisible to the user) then copy whatever Selection you end up building using Selection/Range.Text (or Selection/Range.TextWithRM if you need to copy change tracking as well). Then after you move the Selection to the insertion position (where you want to move/copy the element to) you would just call Selection.PasteString().

Most people find scripting with the Selection/Range objects to be easier than DOM. However, there are probably only rare cases where you might want to mix their use, so if you start with DOM then it can be easiest to use it all the way through your script as well.

What does your exact XML look like before and afterwards? You will need to include all attrs and children so I have a really good idea of what you are doing.

Can we use the user's current selection as the starting point for finding the element to copy? If not, what criteria are you using to locate that element (element name, parent, children, PCDATA, PI, attribute values, etc.)?