Highlighted

Find next marker

Advocate ,
Apr 17, 2016

Copy link to clipboard

Copied

Dear friends,

While it is quite simple to find the next marker with oDoc.NextMarkerInDoc the sequence of the found markers is not that what the user sees in the document: you get the markers in the sequence they were inserted into the document (which may be quite random). To get the same sequence as using the Find dialogue, I need ...

But again my knowledge is to low - see lines 91 or 92:

#target framemaker 
/*  Navigate markers and get them
Document in charge is E:\_DDDprojects\FM-calc\FM-testfiles\NavigateMarkers.fm
Which contains both #calc and Author markers

It turns out that the sequence of marker.NextMarkerInDoc is that of creating the markers.
For the first and last marker the simple method is OK (since absolute postions).
For next and previous the find method must be used.
*/
var oDoc = app.ActiveDoc, oCurrentMarker;
if (!oDoc.ObjectValid ()) {
  alert ("There is no active document.");
} else {
oCurrentMarker =  GetMarker (oDoc, "#calc", "first");                 // OK
  Alert ("marker found = " + oCurrentMarker.MarkerText);
oCurrentMarker =  GetMarker (oDoc, "#calc", "next", oCurrentMarker);  // undefined
  Alert ("marker found = " + oCurrentMarker.MarkerText);
}
 
function GetMarker (oDoc, sMarkerName, sAdverb, oCurrentMarker) { // =============================
// sAdverb may be first, last, previous, next
// returns undefined if sMarkerName not defined in oDoc
// argument oCurrentMarker unused for "first"  
// unfortunately there are no such methods as LastMarkerInDoc or PreviousMarkerInDoc
  var marker, nextMarker, exit, currenMarker;
    markerType = oDoc.GetNamedMarkerType (sMarkerName); // Get the specified marker type.   
    if (!markerType.ObjectValid ()) { return undefined;}
 
  switch (sAdverb) {
    case "first": 
      oCurrentMarker = GetFirstMarker (oDoc, sMarkerName);
      break;
    case "previous": 
      oCurrentMarker = FindNextPrevMarker (oDoc, sMarkerName, "previous", oCurrentMarker);
      break;
    case "next": 
      oCurrentMarker = FindNextPrevMarker (oDoc, sMarkerName, "next", oCurrentMarker);
      break;
    case "last": 
      oCurrentMarker = GetLastMarker (oDoc, sMarkerName);
      break;
    default:
      Alert ("Error in routine NavigateMarker\nUndefined sAdverb = " + sAdverb);
      break;
  }
  return oCurrentMarker;
}

function GetFirstMarker (oDoc, sMarkerName) { // get first marker of type sMarkerName =============
// function returns the current marker, null if it does not exist
// parameter oCurrentMarker is not used
  var marker = null, nextMarker, oCurrentMarker;
  marker = oDoc.FirstMarkerInDoc; 
  while (marker.ObjectValid ()) { 
    nextMarker = marker.NextMarkerInDoc; 
    if (marker.MarkerTypeId.Name === sMarkerName) {
      return marker;
    }
    marker = nextMarker; 
  }
}

function GetLastMarker (oDoc, sMarkerName) { // get last marker of type sMarkerName ===============
// function returns the last marker of type sMarkerName, null if it does not exist
// parameter oCurrentMarker is not used
  var marker, nextMarker, lastMarker;
  marker = oDoc.FirstMarkerInDoc;
  marker = marker.NextMarkerInDoc; 
  while (marker.ObjectValid ()) { 
    if (marker.MarkerTypeId.Name === sMarkerName) {
      lastMarker = marker;
    }
    marker = marker.NextMarkerInDoc; 
  }
  return lastMarker;
}

function FindNextPrevMarker (oDoc, sMarkerName, sAdverb, oCurrentMarker) { // get next/previous ===
// function returns the current marker, null if it does not exist
// Base: Russ Ward in https://forums.adobe.com/message/3888653#3888653
  var marker;
  var tr = new TextRange();
  var findParams = new PropVals();
 
  tr.beg.obj = tr.end.obj = oCurrentMarker;       // Starting tr is the current marker
  tr.beg.offset = tr.end.offset = 0;              //
                                                  // Wrapping not wanted.
  findParams = GetFindParamsMarker (sMarkerName, sAdverb); // Find parameters for marker

  InitFA_errno ();                                // reset - it is write protected
//marker = oDoc.Find(tr.beg, findParams);         // => undefined
  marker = oDoc.Find(oCurrentMarker, findParams); // => undefined
   
  if (FA_errno !== Constants.FE_Success) {
    return undefined;                             // no next/previvious marker present
  }
  return marker;                                  // we have found a next/prev marker
}

function GetFindParamsMarker (sMarkerName, direction) { //=========================================
// Get/set the find parameters: find marker of type sMarkerName, consider direction, no wrapping around
// Returns find parameters in the function

  var findParams;
  if (direction = "next") {
    findParams = AllocatePropVals (1); 
    findParams[0].propIdent.num = Constants.FS_FindMarkerOfType; 
    findParams[0].propVal.valType = Constants.FT_String; 
    findParams[0].propVal.sval = sMarkerName; 
  } else {                                        // previous
    findParams = AllocatePropVals (2); 
    findParams[0].propIdent.num = Constants.FS_FindMarkerOfType; 
    findParams[0].propVal.valType = Constants.FT_String; 
    findParams[0].propVal.sval = sMarkerName; 
    findParams[1].propIdent.num = Constants.FS_FindCustomizationFlags;
    findParams[1].propVal.valType = Constants.FT_Integer;
    findParams[1].propVal.ival = Constants.FF_FIND_BACKWARDS;
  }
  return findParams; 
} // --- end GetFindParams

function InitFA_errno() { //========================================================================
// Reset FA_errno as it is write protected. See https://forums.adobe.com/thread/962910
  app.GetNamedMenu("!MakerMainMenu");             //If this fails, you've got bigger problems
  return;
}

How to specify the (most likely needed) text range?

Thank You

Klaus Daube

I'm back ;-))

Just try this one.

var oDoc = app.ActiveDoc

var oCurrentMarker; 

var docStart = oDoc.MainFlowInDoc.FirstTextFrameInFlow.FirstPgf;

var MarkerList = [];  

var tloc = new TextLoc (docStart, 0);

var locTextRange = new TextRange (tloc, tloc);

oDoc.TextSelection = locTextRange;

  if (!oDoc.ObjectValid ()) { 

      alert ("There is no active document."); 

        }

    else

        {  // gather all markers-locations(objects) and store them in an array (MarkerList)

         var FindParams = GetFindParams()

       

        var foundTextRange = oDoc.Find(tloc, FindParams);

        while (foundTextRange.beg.obj.ObjectValid())

            {

                MarkerList.push(foundTextRange);

                tloc = foundTextRange.end;

                foundTextRange = oDoc.Find(tloc, FindParams);

            }

var FoundMarker = [];

    for (var i = 0; i < MarkerList.length; i++)

        {

        var MarkerTI = oDoc.GetTextForRange (MarkerList, Constants.FTI_MarkerAnchor);

     

        oDoc.TextSelection = MarkerList;

        oDoc.ScrollToText (MarkerList);

        alert("MARKER");

          for (var x = 0; x < MarkerTI.length; x++)

           {

            var oTextItem = MarkerTI;

            FoundMarker.push(oTextItem.obj)//store the marker objects

            }

        }

    } 

function GetFindParams()

{

    var FindParams = new PropVals() ;

    var propVal = new PropVal() ;

    propVal.propIdent.num = Constants.FS_FindWrap ;

    propVal.propVal.valType = Constants.FT_Integer;

    propVal.propVal.ival = 0 ;// don't start at the beginning

    FindParams.push(propVal);

   

    propVal = new PropVal() ;

    propVal.propIdent.num = Constants.FS_FindObject;

    propVal.propVal.valType = Constants.FT_Integer;

    propVal.propVal.ival = Constants.FV_FindAnyMarker ;

    FindParams.push(propVal);

    return FindParams

}

TOPICS
Scripting

Views

815

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more

Find next marker

Advocate ,
Apr 17, 2016

Copy link to clipboard

Copied

Dear friends,

While it is quite simple to find the next marker with oDoc.NextMarkerInDoc the sequence of the found markers is not that what the user sees in the document: you get the markers in the sequence they were inserted into the document (which may be quite random). To get the same sequence as using the Find dialogue, I need ...

But again my knowledge is to low - see lines 91 or 92:

#target framemaker 
/*  Navigate markers and get them
Document in charge is E:\_DDDprojects\FM-calc\FM-testfiles\NavigateMarkers.fm
Which contains both #calc and Author markers

It turns out that the sequence of marker.NextMarkerInDoc is that of creating the markers.
For the first and last marker the simple method is OK (since absolute postions).
For next and previous the find method must be used.
*/
var oDoc = app.ActiveDoc, oCurrentMarker;
if (!oDoc.ObjectValid ()) {
  alert ("There is no active document.");
} else {
oCurrentMarker =  GetMarker (oDoc, "#calc", "first");                 // OK
  Alert ("marker found = " + oCurrentMarker.MarkerText);
oCurrentMarker =  GetMarker (oDoc, "#calc", "next", oCurrentMarker);  // undefined
  Alert ("marker found = " + oCurrentMarker.MarkerText);
}
 
function GetMarker (oDoc, sMarkerName, sAdverb, oCurrentMarker) { // =============================
// sAdverb may be first, last, previous, next
// returns undefined if sMarkerName not defined in oDoc
// argument oCurrentMarker unused for "first"  
// unfortunately there are no such methods as LastMarkerInDoc or PreviousMarkerInDoc
  var marker, nextMarker, exit, currenMarker;
    markerType = oDoc.GetNamedMarkerType (sMarkerName); // Get the specified marker type.   
    if (!markerType.ObjectValid ()) { return undefined;}
 
  switch (sAdverb) {
    case "first": 
      oCurrentMarker = GetFirstMarker (oDoc, sMarkerName);
      break;
    case "previous": 
      oCurrentMarker = FindNextPrevMarker (oDoc, sMarkerName, "previous", oCurrentMarker);
      break;
    case "next": 
      oCurrentMarker = FindNextPrevMarker (oDoc, sMarkerName, "next", oCurrentMarker);
      break;
    case "last": 
      oCurrentMarker = GetLastMarker (oDoc, sMarkerName);
      break;
    default:
      Alert ("Error in routine NavigateMarker\nUndefined sAdverb = " + sAdverb);
      break;
  }
  return oCurrentMarker;
}

function GetFirstMarker (oDoc, sMarkerName) { // get first marker of type sMarkerName =============
// function returns the current marker, null if it does not exist
// parameter oCurrentMarker is not used
  var marker = null, nextMarker, oCurrentMarker;
  marker = oDoc.FirstMarkerInDoc; 
  while (marker.ObjectValid ()) { 
    nextMarker = marker.NextMarkerInDoc; 
    if (marker.MarkerTypeId.Name === sMarkerName) {
      return marker;
    }
    marker = nextMarker; 
  }
}

function GetLastMarker (oDoc, sMarkerName) { // get last marker of type sMarkerName ===============
// function returns the last marker of type sMarkerName, null if it does not exist
// parameter oCurrentMarker is not used
  var marker, nextMarker, lastMarker;
  marker = oDoc.FirstMarkerInDoc;
  marker = marker.NextMarkerInDoc; 
  while (marker.ObjectValid ()) { 
    if (marker.MarkerTypeId.Name === sMarkerName) {
      lastMarker = marker;
    }
    marker = marker.NextMarkerInDoc; 
  }
  return lastMarker;
}

function FindNextPrevMarker (oDoc, sMarkerName, sAdverb, oCurrentMarker) { // get next/previous ===
// function returns the current marker, null if it does not exist
// Base: Russ Ward in https://forums.adobe.com/message/3888653#3888653
  var marker;
  var tr = new TextRange();
  var findParams = new PropVals();
 
  tr.beg.obj = tr.end.obj = oCurrentMarker;       // Starting tr is the current marker
  tr.beg.offset = tr.end.offset = 0;              //
                                                  // Wrapping not wanted.
  findParams = GetFindParamsMarker (sMarkerName, sAdverb); // Find parameters for marker

  InitFA_errno ();                                // reset - it is write protected
//marker = oDoc.Find(tr.beg, findParams);         // => undefined
  marker = oDoc.Find(oCurrentMarker, findParams); // => undefined
   
  if (FA_errno !== Constants.FE_Success) {
    return undefined;                             // no next/previvious marker present
  }
  return marker;                                  // we have found a next/prev marker
}

function GetFindParamsMarker (sMarkerName, direction) { //=========================================
// Get/set the find parameters: find marker of type sMarkerName, consider direction, no wrapping around
// Returns find parameters in the function

  var findParams;
  if (direction = "next") {
    findParams = AllocatePropVals (1); 
    findParams[0].propIdent.num = Constants.FS_FindMarkerOfType; 
    findParams[0].propVal.valType = Constants.FT_String; 
    findParams[0].propVal.sval = sMarkerName; 
  } else {                                        // previous
    findParams = AllocatePropVals (2); 
    findParams[0].propIdent.num = Constants.FS_FindMarkerOfType; 
    findParams[0].propVal.valType = Constants.FT_String; 
    findParams[0].propVal.sval = sMarkerName; 
    findParams[1].propIdent.num = Constants.FS_FindCustomizationFlags;
    findParams[1].propVal.valType = Constants.FT_Integer;
    findParams[1].propVal.ival = Constants.FF_FIND_BACKWARDS;
  }
  return findParams; 
} // --- end GetFindParams

function InitFA_errno() { //========================================================================
// Reset FA_errno as it is write protected. See https://forums.adobe.com/thread/962910
  app.GetNamedMenu("!MakerMainMenu");             //If this fails, you've got bigger problems
  return;
}

How to specify the (most likely needed) text range?

Thank You

Klaus Daube

I'm back ;-))

Just try this one.

var oDoc = app.ActiveDoc

var oCurrentMarker; 

var docStart = oDoc.MainFlowInDoc.FirstTextFrameInFlow.FirstPgf;

var MarkerList = [];  

var tloc = new TextLoc (docStart, 0);

var locTextRange = new TextRange (tloc, tloc);

oDoc.TextSelection = locTextRange;

  if (!oDoc.ObjectValid ()) { 

      alert ("There is no active document."); 

        }

    else

        {  // gather all markers-locations(objects) and store them in an array (MarkerList)

         var FindParams = GetFindParams()

       

        var foundTextRange = oDoc.Find(tloc, FindParams);

        while (foundTextRange.beg.obj.ObjectValid())

            {

                MarkerList.push(foundTextRange);

                tloc = foundTextRange.end;

                foundTextRange = oDoc.Find(tloc, FindParams);

            }

var FoundMarker = [];

    for (var i = 0; i < MarkerList.length; i++)

        {

        var MarkerTI = oDoc.GetTextForRange (MarkerList, Constants.FTI_MarkerAnchor);

     

        oDoc.TextSelection = MarkerList;

        oDoc.ScrollToText (MarkerList);

        alert("MARKER");

          for (var x = 0; x < MarkerTI.length; x++)

           {

            var oTextItem = MarkerTI;

            FoundMarker.push(oTextItem.obj)//store the marker objects

            }

        }

    } 

function GetFindParams()

{

    var FindParams = new PropVals() ;

    var propVal = new PropVal() ;

    propVal.propIdent.num = Constants.FS_FindWrap ;

    propVal.propVal.valType = Constants.FT_Integer;

    propVal.propVal.ival = 0 ;// don't start at the beginning

    FindParams.push(propVal);

   

    propVal = new PropVal() ;

    propVal.propIdent.num = Constants.FS_FindObject;

    propVal.propVal.valType = Constants.FT_Integer;

    propVal.propVal.ival = Constants.FV_FindAnyMarker ;

    FindParams.push(propVal);

    return FindParams

}

TOPICS
Scripting

Views

816

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Apr 17, 2016 0
Enthusiast ,
Apr 21, 2016

Copy link to clipboard

Copied

Hi Klaus,

there are some contstants that are undefined

Constants.FF_FIND_CONSIDER_CASE (0x01)

Constants.FF_FIND_WHOLE_WORD (0x02)

Constants.FF_FIND_USE_WILDCARDS (0x04)

Constants.FF_FIND_BACKWARDS (0x08)

They all return "undefined".

Maybe there are more constants undefined ( I didn't test it yet).

But in FM2015 there was an update this week and since then it works in 2015.

I didn't test it yet with FM 12/11/10.

If you are using FM12 better don't use "Constants.FF_FIND_BACKWARDS" but just type "8" (no quotes).

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Apr 21, 2016 0
Advocate ,
Apr 21, 2016

Copy link to clipboard

Copied

Thanks to Klaus Gobel's answer to my other post I'm very close to a solution: The script finds the next marker of defined type.

But I do not know how to get the new object - as a starting point for the next call of the function:

function FindNextPrevMarker (oDoc, oCurrentMarker) { //

// function returns the nextmarker, null if it does not exist
  var tRange, fRange, marker;
  var tLoc1 = oCurrentMarker.TextLoc;
  var tLoc2 = tLoc1;
  tLoc1.offset = tLoc1.offset+1;                  // Just behind the marker
  tLoc2.offset = tLoc1.offset;
  tRange  = new TextRange(tLoc1,tLoc2);          // TextRange after current marker

  var findParams = new PropVals();                // Get the find parameters for finding marker
    findParams = AllocatePropVals (1); 
    findParams[0].propIdent.num = Constants.FS_FindMarkerOfType; 
    findParams[0].propVal.valType = Constants.FT_String; 
    findParams[0].propVal.sval = "#calc";        // How to find ANY marker ?
// findParams = GetFindParamsMarker (sMarkerName, sAdverb);

  InitFA_errno ();                                // reset - it is write protected

  fRange = oDoc.Find(tRange.beg, findParams);    // finds text range
  oDoc.TextSelection = fRange;                    //?  What is selected?
  oDoc.ScrollToText(fRange);                      //? show it to me 
  marker = fRange.beg.obj;                        // is object Pgf!

  if (FA_errno !== Constants.FE_Success) {
    return undefined;                            // no next/previvious marker present
  }
  return marker;                                  // we have found a next/prev marker
}

Stopping the script at line 22 see that the possible next marker has been selected (item after the 2 -> indicator):

SelectedMarker.png

But the result of my search (line 19) is a paragraph object. How do I get from this the marker object (for the next call of this function)?

Line 21 obviously is wrong.

And BTW would it be correct to start a backwards search with replacing line 06 by:

tLoc1.offset = tLoc1.offset-1;                  // just before the marker

and of course the extended set of the find-paramters as listed in my initial post (function GetFindParamsMarker)

And - what to put in line 14 to find any type of marker, just the next one in sequence?

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Apr 21, 2016 0
Enthusiast ,
Apr 21, 2016

Copy link to clipboard

Copied

If you have found the range, where the marker resides, you need to get the texitem(s):

var FoundMarker = [];

var MarkerRange = oDoc.GetTextForRange (locTrefferListe, Constants.FTI_MarkerAnchor);

              

for (var i = 0; i < MarkerRange.length; i++)//maybe you'll find more markers

     {

     var oTextItem = MarkerRange;

      

     FoundMarker.push(oTextItem.obj)//gather all markers

     }

You're done (with the marker).

To find any marker:

findParams[0].propIdent.num = Constants.FS_FindObject;   

findParams[0].propVal.valType = Constants.FT_Integer;

findParams[0].propVal.ival = Constants.FV_FindAnyMarker;

To ease jumping backward and forward I would suggest to fill an array with the markers.

I will code it in a while, but it will take some time.

Then I'll be back (hasta la vista).

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Apr 21, 2016 0
Enthusiast ,
Apr 21, 2016

Copy link to clipboard

Copied

I'm back ;-))

Just try this one.

var oDoc = app.ActiveDoc

var oCurrentMarker; 

var docStart = oDoc.MainFlowInDoc.FirstTextFrameInFlow.FirstPgf;

var MarkerList = [];  

var tloc = new TextLoc (docStart, 0);

var locTextRange = new TextRange (tloc, tloc);

oDoc.TextSelection = locTextRange;

  if (!oDoc.ObjectValid ()) { 

      alert ("There is no active document."); 

        }

    else

        {  // gather all markers-locations(objects) and store them in an array (MarkerList)

         var FindParams = GetFindParams()

       

        var foundTextRange = oDoc.Find(tloc, FindParams);

        while (foundTextRange.beg.obj.ObjectValid())

            {

                MarkerList.push(foundTextRange);

                tloc = foundTextRange.end;

                foundTextRange = oDoc.Find(tloc, FindParams);

            }

var FoundMarker = [];

    for (var i = 0; i < MarkerList.length; i++)

        {

        var MarkerTI = oDoc.GetTextForRange (MarkerList, Constants.FTI_MarkerAnchor);

     

        oDoc.TextSelection = MarkerList;

        oDoc.ScrollToText (MarkerList);

        alert("MARKER");

          for (var x = 0; x < MarkerTI.length; x++)

           {

            var oTextItem = MarkerTI;

            FoundMarker.push(oTextItem.obj)//store the marker objects

            }

        }

    } 

function GetFindParams()

{

    var FindParams = new PropVals() ;

    var propVal = new PropVal() ;

    propVal.propIdent.num = Constants.FS_FindWrap ;

    propVal.propVal.valType = Constants.FT_Integer;

    propVal.propVal.ival = 0 ;// don't start at the beginning

    FindParams.push(propVal);

   

    propVal = new PropVal() ;

    propVal.propIdent.num = Constants.FS_FindObject;

    propVal.propVal.valType = Constants.FT_Integer;

    propVal.propVal.ival = Constants.FV_FindAnyMarker ;

    FindParams.push(propVal);

    return FindParams

}


					
				
			
			
				
			
			
			
			
			
			
			
		

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Apr 21, 2016 0
K.Daube LATEST
Advocate ,
Apr 22, 2016

Copy link to clipboard

Copied

Thank You Klaus for your response as of

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Apr 22, 2016 0