Highlighted

Find all pages that have marginPreferences overridden from masterSpread

New Here ,
Jan 04, 2017

Copy link to clipboard

Copied

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!

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

Topics

Scripting

Views

1.2K

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 all pages that have marginPreferences overridden from masterSpread

New Here ,
Jan 04, 2017

Copy link to clipboard

Copied

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!

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

Topics

Scripting

Views

1.2K

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
Guide ,
Jan 05, 2017

Copy link to clipboard

Copied

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

Likes

3 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...
Guru ,
Jan 05, 2017

Copy link to clipboard

Copied

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

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...
Guide ,
Jan 05, 2017

Copy link to clipboard

Copied

> 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

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...
New Here ,
Jan 06, 2017

Copy link to clipboard

Copied

Hi Marc,

Thanks for your elaborate answer! I follow your reasoning but because I'm still a novice with Javascript, it will take some time for me to understand the code and implement it. I'll let you know how it goes!

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...
New Here ,
Jan 11, 2017

Copy link to clipboard

Copied

Hi Marc!

I got it working, thanks again!

Although I don't understand why prototyping the DOM is considered dangerous in InDesign. Can this lead to conflicts with other scripts that are running? Or is the extended DOM reset once the script is run?

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...
Guide ,
Jan 11, 2017

Copy link to clipboard

Copied

> Can this lead to conflicts with other scripts that are running?

> Or is the extended DOM reset once the script is run?

I don't think so, except maybe in (weird?) cases where a script would share its target engine with a foreign one

However, what is unquestionable—and this is probably what Trevor was pointing out—is the fact that prototyping DOM related methods requires careful consideration of plural specifiers, should your script use them. Indeed, any of the custom methods I've injected in the above code (say Page.prototype.getMasterPage) will react unexpectedly if you call it from a Pages.everyItem() specifier. Thus, a fully designed prototype should take into account that this may refer to a plural object, which can be checked based on this.getElements().length, and then accordingly operate in returning an array instead of a single object. All this could be done, though. That depends on both your requirements and the recipients of your code. For example, if Page.prototype.getMasterPage() is supposed to work within a framework, my quick implementation obviously lacks robustness. But if you just want it to work in a narrow, fugacious and well defined context, well, it just does its job 😉

@+

Marc

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...
Adobe Community Professional ,
Mar 14, 2019

Copy link to clipboard

Copied

Hi Marc,

your script in reply #1 saved the day with a very peculiar problem with the new Adjust Layout feature with InDesign CC 2019 version 14.0.1.209.

What happened? I had an A1 sized document and wanted to adjust its layout to A4 format like that.

Current values of the document showing:

AdjustLayout-MarginsOnPageOverridden-1.PNG

New Adjust Layout values, page size changed to A4, margins changed to 15 mm, bleed changed to 3 mm, text size should be adjusted as well, also locked page items:

AdjustLayout-MarginsOnPageOverridden-2.PNG

Wrong result of Adjust Layout.

The margins stayed with the overridden values and all elements that were inside of the margins were squeezed inside them like that:

AdjustLayout-MarginsOnPageOverridden-3.PNG

Running your script revealed the culprit.

The overridden margin values.

To fix the issue I reapplied master A with the right margin values to the page and ran the script again, result: no overrides.

AdjustLayout-NoOverridesOfMarginsOnPage-1.PNG

Applied Adjust Layout again and this time the result was as expected:

AdjustLayout-NoOverridesOfMarginsOnPage-3.PNG

Note: The overrides of the margins were not visible in the document.

Why? The margin values were changed on the page from 40 mm ( as applied from master A ) to something else and changed back to their original values.

But of course this did not away with the margin overrides; it just camouflaged the fact that there were overrides.

Regards,
Uwe

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...
Adobe Community Professional ,
Mar 14, 2019

Copy link to clipboard

Copied

After some other tests with Adjust Layout I see that Adjust Layout will only work OK if the margin values of an applied master was not changed after creating the document and if there are no overrides on the margn values on an individual page. That is a very strict limitation of the new feature.

In the case a document was created with e.g. 20 mm margins all around, later in master A the margin values were changed to e.g. 40 mm and then you try to use Adjust Layout with different margins the margins will not change in the result document.

No overrides on the margins. Nothing we can do about that but to detect if there were changes from app.documents[0].marginPreferences to the pages of the document or to the pages of the applied masters. And of course to check if there are any overrides as well.

Regards,
Uwe

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...