Copy link to clipboard
Copied
Hi,
Can anyone in the know tell me if my theory is correct? I have a script that goes through the document using a "find" for every asterisk in a certain style. It then replaces the asterisk with an "asterisk" cross-reference to an endnote, which it creates based on the preceding 6 words or so. It also creates a cross-reference back from the endnote to the asterisk (so there are "clickable" notes in both directions)
Now, when I'm in a "find" loop, I do something like this:
for (var i = 0 ; i < found.length ; i++ ) {
// replace found with a cross-reference
// grab the previous few words behind found.insertionPoints[0]
}
This works OK for the first asterisk. But for the second one l lose a character from the preceding words. And for the third one I lose two characters.
Does ID use a fixed character index – rather than some internal pointer in the document – to refer to each item in "found", so that e.g. if I add "ABCDE" after found[0], found[1].characters[0] will no longer be the second asterisk, but something 5 chars in front of the second asterisk? If that's true, how can I then get to the asterisk that should be at found[1]?
The strange thing is, I have done this with footnotes (using story.footnotes.length) and this doesn't seem to happen.
Sorry if that's rather abstruse, I hope someone gets what I mean.
Thanks,
Alex
1 Correct answer
It is a known effect; it's because the Found array is not "live". That is: if you have an array of items and you change the first one, the next one(s) don't automatically adjust to the new state.
The trick is to process your found items from last to first. Instead of
ukzembla wrote:
for (var i = 0 ; i < found.length ; i++ ) {
...
use this
for (var i=found.length-1; i >= 0; i--) {
...
Copy link to clipboard
Copied
It is a known effect; it's because the Found array is not "live". That is: if you have an array of items and you change the first one, the next one(s) don't automatically adjust to the new state.
The trick is to process your found items from last to first. Instead of
ukzembla wrote:
for (var i = 0 ; i < found.length ; i++ ) {
...
use this
for (var i=found.length-1; i >= 0; i--) {
...
Copy link to clipboard
Copied
Now why didn't I think of that?! I'd started re-coding it with a while loop, resetting the find after every iteration, but I imagine that is much slower than what you just suggested. Thanks very much for your help.
Cheers,
Alex
Copy link to clipboard
Copied
…As a sort of related issue, this might be useful to anyone who, like me, was confused by indexing and insertion:
if p represents a paragraph of 39 characters:
p.characters.length // = 39p.insertionPoints[-1].index // = 39p.insertionPoints[-1] = "ABC" // added "ABC" to end of paragraphp.characters.length // = 43 (correct)p.insertionPoints[-1].index // still = 39, which is WRONG (stale)p.insertionPoints[-1] = "DEF" // means the paragraph ends "DEFABC"// so we have to go up to the story level and
// then back down to get the "live" insertion point:p.parent.characters[p.index + p.characters.length - 1].insertionPoints[-1].contents = "DEF"
Alternatively, you could use a function like:
function realLastCharacter(p) { return p.parent.characters[p.index + p.characters.length - 1];}
Hope that comes in useful for someone, it's not obvious that it will work like that!

