Skip to main content
Participating Frequently
December 1, 2009
Answered

How do I accurately detect overset contents when using tables?

  • December 1, 2009
  • 4 replies
  • 4349 views

Hello, all. I am familiar with how to detect overset contents of a text frame, namely:

if ( myTextFrame.parentStory.contents.length > myTextFrame.contents.length) {

  alert('There is overset text');

} else {

  alert('There is no overset text');

}

However, the contents of my story are three tables, rather than text. Each table contains dozens of cells filled with text. Yet the "length" property of the frame is only 3! How do I accurately read the length of the content given that most of it is in tables so that I can test for overset text?

In case it helps anyone, a more detailed description is:

  1. If there are three tables in the story, and only 2 fit on a page-sized text frame, the length property of that frame will be 2. Kind of weird, but not a problem yet.
  2. In the same scenario, however, if the third table BEGINS on the page but spills over (creating an overset situation), the length property of that frame will be 3 -- causing the test think there is NO overset text! InDesign simply sees 3 characters in the story, and only 3 characters on that page.
  3. When I look at the "contents" property of the story, it just reads 3 squarish characters. They're obviously some kind of special character. InDesign apparently takes the concept of "table" and just writes a placeholder character for it in the "contents" property.

Am I going to have to create some routine to loop through every cell of every table and somehow add it all up to get a proper length? How do I just test for overset-ness?

Thank you!

This topic has been closed for replies.
Correct answer D¡rk Becker

There might be a better way, but I just constructed this expression:

app.activeDocument.stories.item(0).tables.lastItem().cells.lastItem().insertionPoints.lastItem().parentTextFrames.length

;-)

Dirk

4 replies

Inspiring
April 21, 2018

I know this is an old question but I found myself facing the same problem and I think this is a simpler answer. If an insertion point is overset, it's baseline property will not be available. Accessing it throws an error. I'm not sure if there is a way to bypass the error or not, but this seems to work.

To test this, you could create a textbox with a table and type until the table overflows the text box. Then hold shift and hit the back arrow to select one of the overflowing characters

var insertionPoint = app.selection[0].insertionPoints[0];

var isOverset = false;

try { insertionPoint.baseline; }

catch ( error ) { isOverset = true; }

Participating Frequently
December 2, 2009

Harbs, you make an excellent point that overwriting the contents could possibly destroy special formatting/objects if it's not plain text. So I revised my code after realizing that manipulating the contents is actually completely unnecessary in the first place. For anyone searching for help on this issue, here is my final summary of the problem and its solution:

Summary of problem:

InDesign treats a table as a single special character, so it does not accurately report the "overflows" property of a text frame containing a table which spills beyond its margins. A text frame will show as not overflowing (i.e. myTextFrame.overflows will return false) if its final table simply begins within its margins--even if most of the table spills well beyond the text frame. So a ten-page table that starts on page one will only considered by InDesign scripting as being one character long (and therefore shown as fitting completely in first frame even when it doesn't). The solution for this, as discovered by Dirk, is to test whether the final cell of the table overflows.

The solution:

If the final cell of the table is overset (outside the margins of its containing text frame) it will be reported as overflowing (i.e. myFinalCell.overflows will return true). So we just access this cell, and check whether it overflows. However, there's a caveat: the final cell will also show as overflowing when the individual cell's contents overflow its own cell boundaries, as of course it should! So if you just test for overflow, you might end up getting a false positive. So we have to find a way to discriminate between the cases.

To do so, we take advantage of another quirk of the way InDesign reports cell contents: if a cell is outside its containing text frame, its contents are considered empty! So all we have to do is test for both conditions, because a cell which is merely overflowing its own boundaries cannot possibly be empty.

So the test to run is this:

var finalCell = myTextFrame.parentStory.tables.lastItem().cells.lastItem();
if(finalCell.overflows && finalCell.contents=='') {  ...your code here...  }

Of course you'll replace myTextFrame with the one you're dealing with in your own script.

Example usage:

This is how I implemented this in my own script. I have an array of text frames which I pass to this function, and by the time I call the function this array contains only one element, just the first large text frame (with my long table already placed inside it). It also relies on a helper function drawTableFrame which is simple and I'll leave out; it just adds a text frame to the new page and sizes it. And of course myDocument I've long ago set to be the document I'm working in.

// Takes array of text frames, checks for overflow, and adds pages as needed
function addOverflowPages(whichFrameArray) {
    var i = 0;
    var finalCell = whichFrameArray[0].parentStory.tables.lastItem().cells.lastItem();
    while (finalCell.overflows && finalCell.contents=='') {
        i++;
        var newpage = myDocument.pages.add(); // add new page
        whichFrameArray.push(drawTableFrame(newpage)); // draw new frame
        whichFrameArray.previousTextFrame = whichFrameArray[i-1]; // link new frame to previous one
        }
    }

I hope that helps someone! Thanks to everyone for pointing me in the right direction.

Harbs.
Legend
December 2, 2009

I hate to burst your bubble, but if the contents of the cell is TOTALLY overset,the contents will also be empty...

Harbs

Harbs.
Legend
December 1, 2009

1. You are going about basic checking for overset text all wrong. Your

method will return that text is overset if you have a story with two

text frames. You should use the TextFrame.overflows property to check

if it overflows.

2. You have found one of the few holes in InDesign's DOM. There is no

simple way to know if a table (or footnote) overflows. You can check

the parentTextFrames length of the insertionPoints in the cells of the

table, but that's not totally reliable because it will return 0 if the

cell is overset, but also if the text in the cell cannot fit within

the cell.

Harbs

Message was edited by: Harbs. for typos

Peter Kahrel
Community Expert
Community Expert
December 1, 2009

>There is no simple way to know if a table overflows

Well, Dirk's trick works great: if the last cell's first (or any) insertion point's parentTextFrames' length is zero, the table is overset. (Or: if the length of parentTextFrames of any of of the insertionPoints of the last cell of the table is zero, then...).

Peter

Harbs.
Legend
December 1, 2009

Peter, I wrote the same thing...

The problem is, that you get the same length of zero if the cell is placed, but the text in the cell is overset. In those situations, adding additional text frames will not accomplish anything...

Yes, that concept works with footnotes as well. The problem is more defining if a text frame contains (continued) footnotes, since the textframe.footnotes.length will be 0...

Harbs

D¡rk BeckerCorrect answer
Inspiring
December 1, 2009

There might be a better way, but I just constructed this expression:

app.activeDocument.stories.item(0).tables.lastItem().cells.lastItem().insertionPoints.lastItem().parentTextFrames.length

;-)

Dirk

Participating Frequently
December 1, 2009

Dirk's answer works perfectly, as long as the last cell does not itself contain overset text. Harbs very smartly pointed out this loophole, but at least I can control for it or work around it. So Dirk gets the Best Answer!

Harbs' warning is rendered unnecessary in most cases anyway, and Dirk's solution will work in most cases, because cell contents (unless you have a maximumHeight set) usually expand to fit the contents, so an overset cell will be rare. But it does happen, so I wrote a bit of robust code (I hope) to account for it. (This doesn't cover footnotes, but I guess someone could write something similar for them.)

Here is the workaround I found for Harbs' little loophole. All you have to do is temporarily delete the contents of the final cell, re-run the overflow check, and then restore the contents! But you can't just do it inside the parentStory. You have to wait until it is actually drawn on the page! (I explain why at the end.)

Here's the code snippet:

    var cellOverset = false;
    var finalCell = myFrameArray[0].parentStory.tables.lastItem().cells.lastItem();
    while (finalCell.insertionPoints.lastItem().parentTextFrames.length==0) {
        if (finalCell.contents!='' && finalCell.overflows) {
            cellOverset = finalCell.contents;
            finalCell.contents = '';
        } else {
            i++;
            var newpage = myDocument.pages.add(); // add new page
            myFrameArray.push(drawTableFrame(newpage)); // draw new frame
            myFrameArray.previousTextFrame = myFrameArray[i-1]; // link new frame to previous one
        }
    }
    if (cellOverset) {
        finalCell.contents = cellOverset;
        }
    }

Now, this assumes the prior existence of a myFrameArray array, which contains all the linked text frames for my page-spanning table (and which has, by this point in my code, already been loaded with the table). It also assumes the existence of my custom drawTableFrame function, which just draws a new page-wide frame. I leave all that to you.

You'll see that it checks the final cell for having length=0, and if so, it then checks to see if the actual table cell is overflowing AND not an empty string. If so, it clears the contents of the cell and saves them, and re-runs the loop. The loop now adds the final page, links the final frame, and then after the loop exits it restores the contents of the final cell. This can only happen, by the way, after the table has been made visible again! This is because if you try to read or write cell contents that are not yet visible on the page, nothing will happen.

Important note:

There's another quirk (possibly bug?) anyone working with tables might want to be aware of: If the final table cell is overflowing past the visible text frame, its contents are considered empty! That's right, if you run:

app.activeDocument.stories.item(0).tables.lastItem().cells.lastItem().contents

while the cell is hidden from view, even if it is full of text it will have an empty string as its contents! But it is still considered to be overflowing. So:

app.activeDocument.stories.item(0).tables.lastItem().cells.lastItem().overflows

will return true just because it's off the text frame-- even if the contents do not actually overflow the cell boundaries. So keep that in mind when you're thinking of manipulating hidden cell contents or checking for overlows on cells that aren't yet "drawn" on the page.

Harbs.
Legend
December 1, 2009

Nicely done, but be very careful with that function. The way you have it will wipe out any formatiing or inline objects in the cell...

Harbs