2 Replies Latest reply on Sep 25, 2012 10:19 AM by JohnDevlon

    [CS 5.5][JS] Compare characters

    JohnDevlon Level 1

      Hi,

       

      With this post I would like to ask a question.

       

      As part of a larger script, I would like to compare 2 characters. I would like to know if 2 characters look the same. The character itself can be different but do they look the same (color, font size, underline, applied character style, etc)?

       

      Instead of comparing every property of the 2 characters, I've tried a different approche. By removing the content of each character object and then comparing them, they should be the same. Unfortunately this will have unexpected results. Colors swap between letters en the script doesn't detect graphical differences. What am I doing wrong?

       

      What is the best approache to compare characters?

       

      Thanx

       

      John.

       

       

      for (var a = 0; a < app.activeDocument.pages.length; a++){

                  var myCurrentPage = app.activeDocument.pages[a];

       

                  for (var b = 0; b < myCurrentPage.textFrames.length; b++){

                             var myCurrentTextFrame = myCurrentPage.textFrames[b];

                            

                             for (var c = 0; c < myCurrentTextFrame.characters.length-1; c++){

                                      var isEqual = CompareCharacters(myCurrentTextFrame.characters[c], myCurrentTextFrame.characters[c+1]);

                                     

                                      if (isEqual == false){

                                              alert("false")

                                      }

                             }

                 }          

      }

       

      alert("Done !");

       

       

       

      function CompareCharacters(myCurrentChar, myNextChar){

          var isEqual =  true;

       

          var myCurrentCharContents = myCurrentChar.contents.toString();

          var myNextCharContents = myNextChar.contents.toString();

             

          myCurrentChar.contents = "";

          myNextChar.contents = "";

             

         if (myCurrentChar != myNextChar) {

             isEqual =  false;

          }

         

          myCurrentChar.contents = myCurrentCharContents;

          myNextChar.contents = myNextCharContents;

         

          return isEqual;

       

      }

        • 1. Re: [CS 5.5][JS] Compare characters
          Marc Autret Level 4

          Hi John,

           

          Interesting question. The problem is that you need to formally define what you describe as "two characters looking the same."

           

          Your approach cannot work for a simple reason: given a Character instance c1 and a Character instance c2, ExtendScript will never assert c1===c2 unless c1 and c2 resolve to the same location in the document, i.e. have the same index in the same story or container!

           

          This can be easily demonstrated by comparing a character with a pure duplicate:

           

          var sto = app.activeDocument.stories[0],
              c1 = sto.characters[0],
              c2 = c1.duplicate(LocationOptions.AT_END,sto);
          
          alert( c1===c2 ); // => false, simply because c1 and c2 don't share the same location
          

           

          In other words, the only way to assert c1===c2 is to have c1.toSpecifier()==c2.toSpecifier() too. (By the way, note that Character objects are in no way equivalent to strings. Comparing objects and comparing strings are two very different things.)

           

          Thus, to get an efficient comparison routine between objects you still need to determine which properties are relevant, and which are 'negligible'. Considering your example, it seems you want to disregard the following character properties: index, contents, parent, parentStory, parentTextFrames... There are other location properties—such as baseline or horizontalOffset—that you may want to skip.

           

          Now, the most obvious solution to compare Character (or any DOM) objects is to gather all data through the properties property and then to compare each key individually. Here is a possible implementation of this idea:

           

          var compareCharacters = function F(/*Character*/c1, /*Character*/c2)
          // -------------------------------------
          // Return TRUE if some difference is found
          // [check compareCharacters.lastDiff for details]
          // otherwise return FALSE
          {
              // Here are some properties that we won't regard
              // as expressing the 'identity' of a Character.
              // (This list is probably not exhaustive...)
              // ---
              var FF = F.filters || (F.filters = {
                  index: null,
                  // ---
                  contents: null,
                  // ---
                  parent: null,
                  parentStory: null,
                  parentTextFrames: null,
                  // ---
                  baseline: null,
                  horizontalOffset: null,
                  endBaseline: null,
                  endHorizontalOffset: null,
                  // ---
                  bulletChar: null,
                  numberingRestartPolicies: null,
                  });
          
              // Comparison routine
              // ---
              var o1 = c1.properties,
                  o2 = c2.properties,
                  t1, t2, k,
                  r = '';
          
              for( k in o1 )
                  {
                  if( !o1.hasOwnProperty(k) ) continue;
                  if( k in FF ) continue; // filtered prop
                  if( !o2.hasOwnProperty(k) ){ r=k; break; } // missing prop
          
                  t1 = o1[k];
                  t2 = o2[k];
          
                  if( t1 && ('object'==typeof t1) && 'toSource' in t1 )
                      {
                      t1 = t1.toSource();
                      t2 = t2.toSource();
                      }
          
                  if( t1 !== t2 ){ r=k; break; } // not the same value
                  }
          
              // Return
              // ---
              F.lastDiff = r;
              return !!r;
          }
          
          
          // =====================================
          // Sample code
          // =====================================
          
          var doc = app.activeDocument,
              c1 = doc.textFrames[0].characters[0],
              c2 = doc.textFrames[1].characters[1];
          
          if( compareCharacters(c1,c2) )
              {
              alert( "The characters differ in the following property:\r\r" +
                  compareCharacters.lastDiff );
              }
          else
              {
              alert( "The characters are (seen as) equivalent." );
              }
          
          

           

           

          @+

          Marc

          • 2. Re: [CS 5.5][JS] Compare characters
            JohnDevlon Level 1

            Hi Marc,

             

            Many thanks for your detailed feedback and instructions. Your script works super. Your a genius. People like you make the world a better place...

             

            John