Skip to main content
Participant
January 4, 2017
Answered

Find all pages that have marginPreferences overridden from masterSpread

  • January 4, 2017
  • 2 replies
  • 2948 views

Hello,

In a script I'm making, I'm trying to adjust all margins on all pages and masterSpreads.

This adjustment is a formula based on its current marginPreferences so the outcome differs for every page.

The problem is that when I loop through all pages and adjust their marginPreferences, their margins get detached from their respective masterSpreads. This is something that I don't want to happen. However, when I only would loop through the masterSpreads, all pages that have margins that are overridden by the user wouldn't be adjusted.


My solution would be to first loop through all masterSpreads and adjust the margins there. That way, all pages that are based on that masterSpread are updated. I then need to loop through the pages that have marginPreferences that are already overridden by the user and adjust those margins while leaving the other pages alone.

However, I can't find a way to check if a page has its marginPreferences overridden. Can anyone point me in the right direction?

My current code for looping through the masterSpreads is:

for(i=0; i < myDoc.masterSpreads.length; i++){

  for(j=0; j < myDoc.masterSpreads.item(i).pages.length; j++){

    var myMargin = myDoc.masterSpreads.item(i).pages.item(j).marginPreferences;

    myMargin.top = doAdjustmentWith(myMargin.top)

    myMargin.bottom = doAdjustmentWith(myMargin.bottom)

    myMargin.left = doAdjustmentWith(myMargin.left)

    myMargin.right = doAdjustmentWith(myMargin.right)

  }

}

Thanks in advance!

This topic has been closed for replies.
Correct answer Marc Autret

Hi BRVDL,

> I can't find a way to check if a page has its marginPreferences overridden.

> Can anyone point me in the right direction?

That's an interesting problem and I won't pretend to provide a full answer to it. As far as I know, the Scripting DOM does not directly tell us whether myPage's margin preferences actually override its master page settings. That's a missing tool in the box, I'm afraid. So you likely have to implement your own method.

Here is my reasoning. First, if a page P and its master page M do not share the same margin preferences, then we can instantly conclude that P has its prefs overridden. Otherwise, we can't make the decision from just inspecting the prefs—they match!—so we have to check whether they are actually linked. To do so, I suggest we temporarily change a parameter, say columnGutter, at the master level and test if P's gutter undergoes the same change. (Of course one restores the original parameter before returning.)

1. From this, we need a way to compare margin preferences, that is, to decide whether the relevant parameters match. The toSource() method is not a option, because it both adds irrelevant data for our purpose, and does not always reveal the relevant ones. So I've designed a custom marginPrefTrace() method which can be injected in Page.prototype. It returns a string that somehow reflects the margin prefs and can be compared against another trace.

2. In addition—although this appears to be an ancillary issue—we need to get access to the master page of a page. I'm not sure this issue has been already discussed in this forum, but there is no masterPage property, only masterSpread (i.e appliedMaster.) So the problem is to find the corresponding index of P in the collection P.masterSpread.pages. SDK developers have a tool for that (IMasterPage::GetMasterSpreadPageIndex), and “the calculation depends on the index position (0, 1, 2, ...) of the page within its spread and the document set-up” (InDesign CC Programing Guide, Vol 1.) But a generic algorithm hasn't be made available to scripters, AFAIK. Below is an experimental one, Page.prototype.getMasterPage(), which I've not tested in every circumstance and should then be considered a starting point only.

3. Putting all this together, I finally suggest a Page.prototype.overriddenMargins() method—returning either true, false, or undefined—which implements the approach discussed above.

Page.prototype.marginPrefTrace = function F(  o,k,t,a)

// -------------------------------------

// Return a string that reflects the margin

// preferences of this page.

{

    o = F.Q||(F.Q={

        bottom:           'toString',

        left:             'toString',

        right:            'toString',

        top:              'toString',

        columnGutter:     'toString',

        // ---

        columnCount:      'valueOf',

        customColumns:    'valueOf',

        columnDirection:  'valueOf',

        // ---

        columnsPositions: 'toSource',

        });

    t = this.marginPreferences.properties;

    a = [];

    for( k in o )

        o.hasOwnProperty(k) &&

        a.push(t[o]());

    return a.join(',');

};

Page.prototype.getMasterPage = function(  m,n,s)

// -------------------------------------

// Return the master page of this page,

// or NULL if no master applied.

{

    m = this.appliedMaster;

    if( !m || !m.isValid ) return null;

    n = (m=m.pages).length;

    return m[

        2 < n || +PageSideOptions.SINGLE_SIDED==(s=+this.side) ?

        ( this.index % n ) :

        +(s==+PageSideOptions.RIGHT_HAND)

        ];

};

Page.prototype.overriddenMargins = function(  r,m,t,v)

// -------------------------------------

// Tell whether this page has overridden

// margin prefs relative to its master page.

// => TRUE | FALSE | undefined

{

    if( !(m=this.getMasterPage()) )

        return;

    // 1. Simple case (distinct traces.)

    // ---

    if( m.marginPrefTrace() != this.marginPrefTrace() )

        return true;

    // 2. Difficult case (matching traces.)

    // ---

    v = (t=m.marginPreferences).columnGutter;

    t.columnGutter = 1+v;  // change

    r = m.marginPrefTrace() != this.marginPrefTrace();

    t.columnGutter = v;    // restore

    return r;

};

// =====================================

// Test

// =====================================

var doc = app.properties.activeDocument,

    pages = doc && doc.pages.everyItem().getElements(),

    r = [],

    t;

for(

     i=pages.length ;

     i-- ;

     r = (t=pages.pop()).name + ': ' + t.overriddenMargins()

   );

if( r.length ) alert( r.join('\r') );

Hope that helps.

@+

Marc

2 replies

Community Expert
December 14, 2021

FWIW:
Marc's code in the "Correct Answer" was damaged when this thread was moved from the old InDesign Scripting forum to the new InDesign forum about two years ago.

 

Here the correct code that I retrieved from a saved version of this thread from 2018:

Page.prototype.marginPrefTrace = function F(  o,k,t,a)  
// -------------------------------------  
// Return a string that reflects the margin  
// preferences of this page.  
{  
    o = F.Q||(F.Q={  
        bottom:           'toString',  
        left:             'toString',  
        right:            'toString',  
        top:              'toString',  
        columnGutter:     'toString',  
        // ---  
        columnCount:      'valueOf',  
        customColumns:    'valueOf',  
        columnDirection:  'valueOf',  
        // ---  
        columnsPositions: 'toSource',  
        });  
  
    t = this.marginPreferences.properties;  
    a = [];  
    for( k in o )  
        o.hasOwnProperty(k) &&  
        a.push(t[k][o[k]]());  
  
    return a.join(',');  
};  
  
Page.prototype.getMasterPage = function(  m,n,s)  
// -------------------------------------  
// Return the master page of this page,  
// or NULL if no master applied.  
{  
    m = this.appliedMaster;  
    if( !m || !m.isValid ) return null;  
  
    n = (m=m.pages).length;  
  
    return m[  
        2 < n || +PageSideOptions.SINGLE_SIDED==(s=+this.side) ?  
        ( this.index % n ) :  
        +(s==+PageSideOptions.RIGHT_HAND)  
        ];  
};  
  
Page.prototype.overriddenMargins = function(  r,m,t,v)  
// -------------------------------------  
// Tell whether this page has overridden  
// margin prefs relative to its master page.  
// => TRUE | FALSE | undefined  
{  
    if( !(m=this.getMasterPage()) )  
        return;  
  
    // 1. Simple case (distinct traces.)  
    // ---  
    if( m.marginPrefTrace() != this.marginPrefTrace() )  
        return true;  
  
    // 2. Difficult case (matching traces.)  
    // ---  
    v = (t=m.marginPreferences).columnGutter;  
    t.columnGutter = 1+v;  // change  
    r = m.marginPrefTrace() != this.marginPrefTrace();  
    t.columnGutter = v;    // restore  
  
    return r;  
};  
  
  
// =====================================  
// Test  
// =====================================  
  
var doc = app.properties.activeDocument,  
    pages = doc && doc.pages.everyItem().getElements(),  
    r = [],  
    t;  
  
for(  
     i=pages.length ;  
     i-- ;  
     r[i] = (t=pages.pop()).name + ': ' + t.overriddenMargins()  
   );  
  
if( r.length ) alert( r.join('\r') );

 

Tested the code successfully with InDesign 2022 version 17.0.1.105 on Windows 10.

 

Regards,
Uwe Laubender

( ACP )

Marc Autret
Marc AutretCorrect answer
Legend
January 5, 2017

Hi BRVDL,

> I can't find a way to check if a page has its marginPreferences overridden.

> Can anyone point me in the right direction?

That's an interesting problem and I won't pretend to provide a full answer to it. As far as I know, the Scripting DOM does not directly tell us whether myPage's margin preferences actually override its master page settings. That's a missing tool in the box, I'm afraid. So you likely have to implement your own method.

Here is my reasoning. First, if a page P and its master page M do not share the same margin preferences, then we can instantly conclude that P has its prefs overridden. Otherwise, we can't make the decision from just inspecting the prefs—they match!—so we have to check whether they are actually linked. To do so, I suggest we temporarily change a parameter, say columnGutter, at the master level and test if P's gutter undergoes the same change. (Of course one restores the original parameter before returning.)

1. From this, we need a way to compare margin preferences, that is, to decide whether the relevant parameters match. The toSource() method is not a option, because it both adds irrelevant data for our purpose, and does not always reveal the relevant ones. So I've designed a custom marginPrefTrace() method which can be injected in Page.prototype. It returns a string that somehow reflects the margin prefs and can be compared against another trace.

2. In addition—although this appears to be an ancillary issue—we need to get access to the master page of a page. I'm not sure this issue has been already discussed in this forum, but there is no masterPage property, only masterSpread (i.e appliedMaster.) So the problem is to find the corresponding index of P in the collection P.masterSpread.pages. SDK developers have a tool for that (IMasterPage::GetMasterSpreadPageIndex), and “the calculation depends on the index position (0, 1, 2, ...) of the page within its spread and the document set-up” (InDesign CC Programing Guide, Vol 1.) But a generic algorithm hasn't be made available to scripters, AFAIK. Below is an experimental one, Page.prototype.getMasterPage(), which I've not tested in every circumstance and should then be considered a starting point only.

3. Putting all this together, I finally suggest a Page.prototype.overriddenMargins() method—returning either true, false, or undefined—which implements the approach discussed above.

Page.prototype.marginPrefTrace = function F(  o,k,t,a)

// -------------------------------------

// Return a string that reflects the margin

// preferences of this page.

{

    o = F.Q||(F.Q={

        bottom:           'toString',

        left:             'toString',

        right:            'toString',

        top:              'toString',

        columnGutter:     'toString',

        // ---

        columnCount:      'valueOf',

        customColumns:    'valueOf',

        columnDirection:  'valueOf',

        // ---

        columnsPositions: 'toSource',

        });

    t = this.marginPreferences.properties;

    a = [];

    for( k in o )

        o.hasOwnProperty(k) &&

        a.push(t[o]());

    return a.join(',');

};

Page.prototype.getMasterPage = function(  m,n,s)

// -------------------------------------

// Return the master page of this page,

// or NULL if no master applied.

{

    m = this.appliedMaster;

    if( !m || !m.isValid ) return null;

    n = (m=m.pages).length;

    return m[

        2 < n || +PageSideOptions.SINGLE_SIDED==(s=+this.side) ?

        ( this.index % n ) :

        +(s==+PageSideOptions.RIGHT_HAND)

        ];

};

Page.prototype.overriddenMargins = function(  r,m,t,v)

// -------------------------------------

// Tell whether this page has overridden

// margin prefs relative to its master page.

// => TRUE | FALSE | undefined

{

    if( !(m=this.getMasterPage()) )

        return;

    // 1. Simple case (distinct traces.)

    // ---

    if( m.marginPrefTrace() != this.marginPrefTrace() )

        return true;

    // 2. Difficult case (matching traces.)

    // ---

    v = (t=m.marginPreferences).columnGutter;

    t.columnGutter = 1+v;  // change

    r = m.marginPrefTrace() != this.marginPrefTrace();

    t.columnGutter = v;    // restore

    return r;

};

// =====================================

// Test

// =====================================

var doc = app.properties.activeDocument,

    pages = doc && doc.pages.everyItem().getElements(),

    r = [],

    t;

for(

     i=pages.length ;

     i-- ;

     r = (t=pages.pop()).name + ': ' + t.overriddenMargins()

   );

if( r.length ) alert( r.join('\r') );

Hope that helps.

@+

Marc

Trevor:
Legend
January 5, 2017

Nice one Marc,

Not so sure that's it's a good idea to prototype the DOM but either way it's a nice one.

Trevor

Marc Autret
Legend
January 5, 2017

> Not so sure that's it's a good idea to prototype the DOM.

Yeah I know that's still a huge controversy but from time to time I like to live dangerously ;-)

@+

Marc