Skip to main content
daitranthanhoa
Inspiring
August 23, 2023
Question

How can get parentTextFrame of a Cell was Overflow?

  • August 23, 2023
  • 3 replies
  • 789 views

I have a Table put in Link Frame:

 

I want get Parent TextFrame of Cells in Link Frame 2:

If Cell is not overflow, i can get by code:

oCell.texts(1).insertionPoints(1).parentTextFrames(1)

 

But If Cell overflow, above code can't get Parent TextFrame.

How can get parentTextFrame of a Cell was Overflow?

This topic has been closed for replies.

3 replies

Community Expert
August 23, 2023

Nice one, Mark. Maybe if you recompose the cell after removing the zero-width space it'll go back to its original state.

m1b
Community Expert
Community Expert
August 23, 2023

Thanks @Peter Kahrel, it didn't work in this case because the "original state" was incorrect. See my comment above. - Mark

m1b
Community Expert
Community Expert
August 23, 2023

Hi @daitranthanhoa, I have written a function that gets this. Here you go:

 

/**
 * Return a cell's parent text frame.
 * @author m1b
 * @version 2022-08-18
 * Note: getting the parent text frame is a challenge when
 * there are no insertion points due to overset text, so
 * here we add a zero-width space as the first character
 * therefore the first insertionPoint will now be active
 * @param {Cell} cell - an Indesign Table Cell.
 * @returns {TextFrame}
 */
function getParentTextFrame(cell) {

    if (!cell.isValid)
        return;

    // insert zero-width space to expose first
    // insertion point in case where cell is overset
    cell.insertionPoints[0].contents = '\u200B';

    // get the text frame
    var textFrame = cell.insertionPoints[0].parentTextFrames[0];

    // clean up
    cell.characters[0].remove();
    cell.recompose();

    if (
        textFrame != undefined
        && textFrame.isValid
    )
        return textFrame;

};

Edit 2023-08-23: as per @Peter Kahrel's great suggestion, I added cell.recompose() after removing the zero-width space. This did make a slight difference when I tested on every cell of @daitranthanhoa sample document (see attached).

 

daitranthanhoa
Inspiring
August 23, 2023

Some Rows will change Parent TextFrame, If Insert character  "\u200B"

 

m1b
Community Expert
Community Expert
August 23, 2023

Hi @daitranthanhoa, I have looked at your demo file and it was very helpful, thanks. With a bit of investigation, I believe I can describe the problem you are seeing now. It is this:

 

It is possible to get an overset autogrow table cell having the wrong height.

 

To do it deliberately, do the following:

1. make a basic table with cells set to "At least" height (not "Exact") (sorry please translate to Japanese)

2. select the text of a cell and by typing the value into the Character Panel, set the point size to a size greater than the current cell height can accommodate. (Do not use the up and down arrows to change the size—this will not trigger the bug.)

So this is obvbiously a bug because Indesign is *temporarily* calculating the cell height incorrectly, and as soon as you do anything to the cell contents in some other way (eg. by adding a character that isn't overflowing), it will correctly calculate the cell height (and in your example case, causing the row to jump to the next frame).

 

Therefore, my script function is correctly showing the parent TextFrame, but the Indesign DOM is not.

 

What is the solution? I'm not sure how best to make a script fix the cell height problem but, for example, these will force it to show the correct height and flow correctly:

(a) adding a character to the first insertionPoint that isn't overflowing, eg. a zero-width space (as you noticed),

(b) changing the pointSize of a character in the overflowed section.

 

I am going to update my function to better handle this, because currently it will give the wrong parent textframe for other cells in the row with the problem cell.

- Mark


Okay, I've written a variant of the function that is better because it will give the correct result in cases such as yours.

 

/**
 * Demo showing function that returns parent text frame of a table row.
 *  m1b
 * @discussion https://community.adobe.com/t5/indesign-discussions/how-can-get-parenttextframe-of-a-cell-was-overflow/m-p/14030313
 */
function main() {

    var doc = app.activeDocument,
        table = doc.stories.everyItem().tables[0],
        rows = table.rows.everyItem().getElements(),
        result = [];

    for (var i = 0; i < rows.length; i++) {
        var parentFrame = getRowParentTextFrame(rows[i]);
        if (parentFrame)
            result.push('row: ' + rows[i].index + '  parentFrame.id: ' + parentFrame.id);
    }

    alert('Results:\n'+result.join('\n'));

}
app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, 'Do Script');


/**
 * Return a row's parent text frame.
 *  m1b
 *  2023-08-24
 * Note: getting the parent text frame is a challenge when
 * there are no insertion points due to overset text, so
 * here we add a zero-width space as the first character
 * therefore the first insertionPoint will now be active
 * Note: another complication is a bug where indesign will
 * display the incorrect height for an autogrowing, overflowing
 * cell, and place the cell in the wrong parent text frame.
 * (See explanation here: https://community.adobe.com/t5/indesign-discussions/how-can-get-parenttextframe-of-a-cell-was-overflow/m-p/14030313
 *  {Row} row - an Indesign Table Row.
 *  {TextFrame}
 */
function getRowParentTextFrame(row) {

    if (!row.isValid)
        return;

    var cells = row.cells,
        parentTextFrames = row.parent.parent.parentStory.textContainers,
        rowTextFrameIDs = {},
        rowTextFrame;

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

        var cell = cells[i];

        // insert zero-width space to expose first
        // insertion point in case where cell is overset
        cell.insertionPoints[0].contents = '\u200B';

        // store the parent frame index of this cell
        rowTextFrameIDs[cell.insertionPoints[0].parentTextFrames[0].id] = true;

        // clean up
        cell.characters[0].remove();

    }

    // match it to the *last-most* parentTextFrame
    parentFrameLoop:
    for (var j = parentTextFrames.length - 1; j >= 0; j--) {
        if (rowTextFrameIDs[parentTextFrames[j].id] == true) {
            rowTextFrame = parentTextFrames[j];
            break parentFrameLoop;
        }
    }

    if (
        rowTextFrame != undefined
        && rowTextFrame.isValid
    )
        return rowTextFrame;

};

 

 

By the way, if you *really* want it to return the text frame that it current (incorrectly!) appears to be in, you can change

 

for (var j = parentTextFrames.length - 1; j >= 0; j--) {

 

 to

 

for (var j = 0; j < parentTextFrames.length; j++) {

 

- Mark

 

Edit 2023-08-24: added my sample .indd for anyone to run the test script with.

Willi Adelberger
Community Expert
Community Expert
August 23, 2023

What do you want to afford with a table on the master/parent page? As content should not be there.