9 Replies Latest reply on Aug 16, 2013 7:44 AM by LinusCMH

    Insert text without picking up local overrides

    LinusCMH

      Okay, time to give up and ask for help....

       

      I'm trying to write an Extendscript that will insert tags around a text style range without picking up the formatting of the text style range. For example, I would like to find the italicized "Photography Theory" in the middle of a paragraph of non-italic text like this:

       

      My own thoughts about the very strange second volume of that series, Photography Theory, are in “Is Anyone Listening?,” Photofile 80 (Winter 2007): 80.

       

      and put "<i> before and "</i>" after it. I am able to add the tags using the insertionPoint object, but the closing tag takes on the formatting of the text style range. Rather, I need it to take on the underlying applied paragraph style with no modifications.

       

      I have tried using insertionPoint.clearOverrides both before and after the insertion of the tag, but that doesn't work.

       

      Because there are too many kinds of "italic" font styles—oblique, cursive, kursive, cursiv, slanted, and on and on—I can't use find/change.

       

      I would be open to using a find routine later in the script that searches for "<i>" and "</i>" and clears the overrides on them, but again, I can't do it with a change function, so I would have to find each tag one at a time then apply a clearOverrides to it. That seems to me like it would be incredibly slow, so I'd rather not go that route. (Also, this is my first Extendscript, and I can figure out how to do the loop that it would iterate through each instance and then stop—I can do it in my sleep with a do loop in VBA, but I'm not there yet with Javascript).

       

      Thanks for any thoughts on how to plant the tag without it picking up overrides.

       

      m.

        • 1. Re: Insert text without picking up local overrides
          Laubender Adobe Community Professional & MVP

          @LinusCMH – I think the problem here is that the last insertion point of the text style range includes all the formatting you want to avoid.

           

          What you could do:
          Create the "tags" in a new text frame (in fact they are no "tags", but chunks of formatted text), apply the right formatting and move the opening and the closing "tags" to the appropriate insertion points. Afterwards you can remove the temp text frame.

           

          Do not attempt that with the "contents" property of the insertion point, but with the "texts" object.

           

          One example code:

          Supposed the italic text you want to surround by "tags" is selected…

           

          var sel = app.selection[0];
          
          var myClosingInsertionPoint = sel.insertionPoints[-1];
          var myOpeningInsertionPoint = sel.insertionPoints[0];
          
          var myParaStyle = sel.appliedParagraphStyle;
          var myTempTF = app.documents[0].textFrames.add({geometricBounds:[0,0,100,100]});
          
          myTempTF.texts[0].appliedParagraphStyle = myParaStyle;
          myTempTF.texts[0].contents = "<i>"+"</i>";
          
          myTempTF.texts[0].characters.itemByRange(3,6).move(LocationOptions.AFTER,myClosingInsertionPoint);
          myTempTF.texts[0].characters.itemByRange(0,2).move(LocationOptions.AFTER,myOpeningInsertionPoint);
          
          myTempTF.remove();
          

           

          Since I do not know your code, I cannot say, if you can implement that suggestion easily…

           

          Uwe

          • 2. Re: Insert text without picking up local overrides
            Laubender Adobe Community Professional & MVP

            Oh. And if you want to re-use the temp text frame and its texts object, do not use the move() method, but duplicate() the characters.

             

            var sel = app.selection[0];
            
            var myClosingInsertionPoint = sel.insertionPoints[-1];
            var myOpeningInsertionPoint = sel.insertionPoints[0];
            
            var paraStyle = sel.appliedParagraphStyle;
            var myTempTF = app.documents[0].textFrames.add({geometricBounds:[0,0,100,100]});
            
            myTempTF.texts[0].appliedParagraphStyle = paraStyle;
            myTempTF.texts[0].contents = "<i>"+"</i>";
            
            myTempTF.texts[0].characters.itemByRange(3,6).duplicate(LocationOptions.AFTER,myClosingInsertionPoint);
            myTempTF.texts[0].characters.itemByRange(0,2).duplicate(LocationOptions.AFTER,myOpeningInsertionPoint);
            

             

            Uwe

            • 3. Re: Insert text without picking up local overrides
              TᴀW Adobe Community Professional & MVP

              I would have thought that Linus's orignal approach is the most obvious

              one: first remove any character overrides from the final insertionPoint,

              then add the text.

               

              Yet, strangely, when I try remove the overrides from the last

              insertionPoint, the whole word previous loses its formatting. That is

              unexpected.

               

              So, a question to the OP: is that the behavious you're getting also? You

              don't say what happens when you clear the overrides of the final

              insertionPoint -- just that it doesn't work.

               

              I also though of Laubender's suggestions, but it is probably slower, and

              seems like an unnecessary workaround.

               

              Ariel

              • 4. Re: Insert text without picking up local overrides
                Laubender Adobe Community Professional & MVP

                @Ariel – without seeing any code from the OP it's hard to make suggestions…
                My code might be slow, but its working flawlessly.

                 

                About losing formatting of the last word: yes, this is unexpected.
                But I experience something different:

                 

                myInsertionPoint.clearOverrides();
                

                 

                or:

                 

                myInsertionPoint.clearOverrides(OverrideType.CHARACTER_ONLY);
                

                 

                clears the overrides from the whole paragraph!


                (except character styles, which are no overrides)

                 

                You need at least one single character to get the clearOverrides() right. Provided it is (edit:) not (/edit) formatted with a character style!


                If the italic text style range is formatted by a character style, clearOverrides() does nothing, if you added "</i>" to the last insertion point with myIinsertionPoint.contents = "</i>", because the character style is also added and could not be cleared with: clearOverrides(OverrideType.CHARACTER_ONLY).

                 

                So I think the safest way is to move or duplicate preformatted chunks of text to the insertion point…

                 

                Uwe

                 

                Message was edited by: Laubender

                • 5. Re: Insert text without picking up local overrides
                  TᴀW Adobe Community Professional & MVP

                  Yes, you're right: it affects the whole paragraph. A bit weird, but now

                  that I think about it, consistent with the UI.

                   

                  In the UI, if you put the cursor anywhere in a paragraph without

                  selecting anything, and click "Clear overrides", the entire paragraph is

                  affected.

                   

                  But if you select a character or some letters, and click "clear

                  overrides", only the selection is affected.

                   

                  That seems to be what's going on with the script route as well.

                   

                  Ariel

                  • 6. Re: Insert text without picking up local overrides
                    [Jongware] Most Valuable Participant

                    Is it important that the tags don't get any additional formatting? (I would qualify it as "neat" rather than "crucial" but then again, "working neatly" is important IMO.)

                     

                    This is what I came up with. You don't say how you are currently checking the TextStyleRanges, but in case you are using the "everyItem().getElements()" trick to speed things up, do not attempt this on my script. You cannot cache the styling ranges in a simple way because you will be actively changing them. I didn't bother working it out in detail, maybe it's possible.

                     

                    There are a couple of tricks in the following script: it marks italic/non-italic boundaries and ignores any other formatting changes and it picks up "the" formatting for the tags from the current applied paragraph style. Since there is no single "formatting" object, you have to 'apply' every single attribute you are interested in -- color, size, superscript, capitalization, strikeout gap color percentage, or whatever attributes you need.

                     

                    The final 'exception' line is because this way you are checking italic/non-italic ends only, and so you need one other check for the very first word.

                     

                     

                    fmtr = app.selection[0].parentStory.textStyleRanges;
                    inItalic = false;
                    for (i=fmtr.length-1; i >=0; i--)
                    {
                      if (fmtr[i].appliedFont.fontStyleName == "Italic")
                      {
                        if (!inItalic)
                        {
                          inItalic = true;
                          fmtr[i].insertionPoints[-1].properties = {contents:'</i>', appliedFont:fmtr[i].appliedParagraphStyle.appliedFont, underline:fmtr[i].appliedParagraphStyle.underline};
                        }
                      } else
                      {
                        if (inItalic)
                        {
                          inItalic = false;
                          fmtr[i].insertionPoints[-1].properties = {contents:'<i>', appliedFont:fmtr[i].appliedParagraphStyle.appliedFont, underline:fmtr[i].appliedParagraphStyle.underline};
                        }
                      }
                    }
                    // very first word in Italic is an exception
                    if (inItalic)
                      fmtr[0].insertionPoints[0].properties = {contents:'<i>', appliedFont:fmtr[i].appliedParagraphStyle.appliedFont, underline:fmtr[i].appliedParagraphStyle.underline};
                    
                    1 person found this helpful
                    • 7. Re: Insert text without picking up local overrides
                      Laubender Adobe Community Professional & MVP

                      Is it important that the tags don't get any additional formatting? (I would qualify it as "neat" rather than "crucial" but then again, "working neatly" is important IMO.)

                      @Jongware – that is a crucial point. "Tagging" a formatted text with text like <i> … </i> usually means that the text is used unformatted at a future step in the workflow. So it really doesn't matter, if the closing tag is formatted or not…

                       

                      Let's see what the OP has to say…

                       

                      Uwe

                      • 8. Re: Insert text without picking up local overrides
                        Laubender Adobe Community Professional & MVP

                        @Jongware – just tested your snippet.
                        1. It works well, if the Italic text style ranges are not formatted with a character style ("Italic").

                         

                        2. It does work halfway, if the a character style ("Italic") is applied: the end tag will show the formatting of the character style.

                         

                        3. It does not work at all (no tags applied), if a GREP style is used for the Italic text style ranges.

                        Wheras a Text Search or a GREP Search in the UI is finding* the Italic formatting used by a GREP style.

                         

                        *surprisingly all occasions but the last one in my test document:
                        I did a GREP Style for \d+ using a character style set to "Italic".
                        Have to do some more testing, if this is a bug in my InDesign CS5.5 on OSX 10.6.8.

                         

                        Here a screen shot from my German UI (sorry, might be confusing at the first glance).


                        The alert at the bottom means: "Search ended" (no furher instances found). But obviously there is another one not found just in the next paragraph. The scope of the search is set to document wide!

                         

                        GREPSearchForItalic.png

                         

                        Uwe

                        • 9. Re: Insert text without picking up local overrides
                          LinusCMH Level 1

                          Thanks for all of your help and suggestions and for being so quick to reply.

                           

                          What was happening was that even though I used the clear overrides method, the terminal tag still took on the formatting of the text style range—that is, it was still italic.

                           

                          What I ended up doing was applying to the last insertion point the font style of the underlying paragraph style definition. However....

                           

                          I came to a conclusion similar to Jongware's. It is important that the formatting of the opening and closing tags match each other, but it's not critical that they discard the overrides. Rather, I now think that they should take on the character formatting of the text style range, in effect, extending the text style range. For the terminal tag, this is easy in that it already takes on the formatting of the range. For the opening tag, though, I had to "replace" the first character in the text style range with a string that consisted of my tag appended to the first character of the text style range. That was the only way (and the least code-intensive way) I could thing of to capture the formatting of the text style range and apply it to the opening tag.

                           

                          The reason that the tags need to match each other and match the text style range is that I will be testing text style ranges for more than one condition (italic, bold, and small caps for now, but probably more later), and if the first tags I plant differ from each other, subsequent tags start to get tangled. For example, if I were to tag an italic word that also has small-caps appied, and if the italic tags didn't match each other, I would end up with <i><sc>italic word</i></sc>. By ensuring that hte formatting of the tags matches, I get <sc><i>italic word</i></sc>.

                           

                          @Jongware: I am not using the "everyItem().getElements()" trick; I'm still very new to this and don't know how I would do that. I'm just iterating through the text style ranges with a counter. It's slow (it takes about 1/2 hour to process a 200-ish page book), but my goal right now is to get it working. I'll speed it up as I learn more about Javascript. I do like how you're iterating through the text style ranges, though (building an array), and will give that a try in my code.

                           

                          @Laubender: You're right; I'm prepping files for export to xhtml. I don't like some of the things InDesign does (or doesn't do) when exporting EPUBs, so I'm trying to massage the file before export. I have a corresponding Word macro that goes into each xhtml file and finishes the cleanup process. The biggest problem for me is capturing local formatting that would otherwise be lost or would be so generic in the CSS that I would have to spend too much time cleaning it up.

                           

                          @Ariel: I didn't look at the rest of the paragraph, unfortunately. When I saw that my tag was still formatted, I returned to the code. I can't say if I was seeing the behavior you describe, but I suspect that would be the case.

                           

                          Thanks again, everyone.

                          Matthew