Автоматический подгон ширины колонки под контент.

  • Автор темы Автор темы dim4an
  • Дата начала Дата начала
Статус
Закрыто для дальнейших ответов.

dim4an

Участник
Топикстартер
Сообщения
93
Реакции
1
Всем привет.
Реализую такую задачу. Есть некий шаблон таблицы. В этой таблице может быть от 2 до n количество столбцов. Каждый столбец должен быть выравнен под контент находящийся в нем. Контент(текст) может располагаться только в 1 строчку. Тут то и возникает проблема, так как колонка не имеет метод fit или свойство auto size.
На ум приходит мысль реализовать это самому, по следующему алгоритму. Ставим для колонок флаг autoGrow в false, что бы текст не мог расположиться в 2 строчки. Проходим по колонкам и ячейкам в них, смотрим есть ли ячейки в которых не уместился текст, если есть, то допустим увеличиваем ширину колонки на 0.2 мм, опять проверяем, уместился ли текст и та к до тех пор, пока текст не уместится. Соответственно, для тех колонок, в которых текст уместился сразу, мы уменьшаем ширину, до тех пор, пока он перестанет умещаться.
По логике все работает, но что если у нас более 1000 таких таблиц и скорость работы скрипта очень важна.

Есть ли какие то варианты по оптимизации алгоритма, или же другие варианты решения проблемы?
 
http://forum.rudtp.ru/resources/tochnoe-vyravnivanie-tablicy.43/
И там необязательно только в одну строчку контент.
Да, читал прежде чем создать тему :) Но, мне этот вариант не подходит... я разрабатываю скрипт для Indisign Server, на выходе должен получится готовый документ, не нуждающийся в доработках.
 
http://forum.rudtp.ru/resources/tochnoe-vyravnivanie-tablicy.43/
И там необязательно только в одну строчку контент.
Переоценил я свои силы, не как не могу добиться нужного мне результата. Ваша функция fitColumnWidthToText() выравнивает колонку под строку с максимальным размером(?). Мне же нужно что бы текст был всегда в одну строчку в каждой ячейки колонки. Решил переделать вашу функцию, под свои нужды. Вот что получилось.
Код:
TextFrame.prototype.fitTableColumnWidthToText = function(){
    var maxLen = 0;
    var myLen = 0;
    var myLen1 = 0;
    var myLenSumm;
    var myT;
    var myCells;
    var table;

    try{
        var table = this.tables[0];
    }catch(e){
        log.write("textFrame has no table");
        return;
    }

    var myCol = table.columns;

    for (k=0;k<myCol.length;k++){
        maxLen = 0;     
        myCells=myCol[k].cells;
        for (i=0; i<myCells.length; i++){
            myLenSumm = 0; 
            if (myCells[i].columns.length==1){//Если ячейка - это несколько сгруппированных ячеек с разных колонок, - ничего не выйдет
                myT = myCells[i].lines;
                    for (j=0;j<myT.length;j++){
                        try{
                            var ab = myT[j].insertionPoints[0].horizontalOffset - myCells[i].leftInset;
                            myLen = myT[j].insertionPoints[-1].horizontalOffset - ab;
                        }catch(e){}
                        try{myLen1 = myT[j].insertionPoints[-2].horizontalOffset - ab;}catch(e2){myLen1 = 0;}
                        if (myLen1 > myLen){myLen = myLen1;}
                        myLenSumm += myLen;         
                    }
                    if(myLenSumm > maxLen) {maxLen = myLenSumm; }
                }
            }
        if(maxLen > 1) myCol[k].width = maxLen;
    }
}

в myLenSumm должна содержать сумму длин всех строк, которые находятся в ячейки. Но на деле эта длина не соответствует действительности. Текст в ячейке все равно перескакивает на следующую строчку.

Не смог найти информацию по поводу myT[j].insertionPoints[0], myT[j].insertionPoints[-1], myT[j].insertionPoints[-2] в чем их различие, что в них содержится?
 
insertionPoint — точка вставки, или, грубо говоря, положение курсора в тексте.
myT[j].insertionPoints[0] — это положение курсора перед первым символом в строке myT[j].
myT[j].insertionPoints[-1] — курсор после последнего символа в этой строке, последняя точка вставки. [-2] — предпоследняя.
Почему сравниваются координаты последней и предпоследней этих точек, досконально не помню (давно отладка была), но, по-моему там что-то связано с символом конца абзаца (если строка заканчивается им). Приходится проверять координаты предпоследней точки и сравнивать с последней. Помню, что так было надо.))
Вероятно, если Вам нужна именно сумма всех строк текста в ячейке, то путаница также связана с этим фрагментом. Более точно пока не скажу.
 
  • Спасибо
Реакции: dim4an
insertionPoint — точка вставки, или, грубо говоря, положение курсора в тексте.
myT[j].insertionPoints[0] — это положение курсора перед первым символом в строке myT[j].
myT[j].insertionPoints[-1] — курсор после последнего символа в этой строке, последняя точка вставки. [-2] — предпоследняя.
Почему сравниваются координаты последней и предпоследней этих точек, досконально не помню (давно отладка была), но, по-моему там что-то связано с символом конца абзаца (если строка заканчивается им). Приходится проверять координаты предпоследней точки и сравнивать с последней. Помню, что так было надо.))
Вероятно, если Вам нужна именно сумма всех строк текста в ячейке, то путаница также связана с этим фрагментом. Более точно пока не скажу.
Спасибо за информацию. Доберусь до рабочего места, попробую что нибудь новенькое выдумать на основе этих данных.
Но вот еще 1 вопрос возник, а если у нас текст не помещается в ячейку, то как он представится как 1 строка или же как то иначе?
 
если у нас текст не помещается в ячейку, то как он представится
Такие вещи проверяются простым алертом.
Выделив переполненную ячейку:
Код:
alert(app.activeDocument.selection[0].lines.length);
Сразу скажу, результат будет равен количеству вмещённых строк + количеству невмещённых абзацев.
Существенно здесь то, что у вытесненного материала, разумеется, отсутствуют координаты (у текста, например, не получить значения horizontalOffset, а у инлайнового фрейма — geometricBounds). Так что в Вашем алгоритме дополнительно придётся делать проверку ячейки на cell.overflows и принимать меры.
 
  • Спасибо
Реакции: dim4an
эх.. если бы все было так просто, только вот где взять корректно и быстро работающий код функции resizeCell()
В этом нет ничего принципиально сложного — алгоритмы разработаны давно.
Предположим, что ячейка в столбце одна (если несколько, то берется, естественно, ячейка с самым большим количеством линий) и в ячейке нет символов, принудительно разбивающих текст на линии.
Первое часть: получаем ширину ячейки и количество линий. Если линий больше, чем одна, устанавливаем ширину ячейки как шир_ячейки х кол_линий. Если линий снова не одна — повторяем. Если опять не одна — скорее всего текст бьется на линии принудительно. По желанию можно оформить в цикле while, установив проверку на максимально допустимую ширину ячейки. Первая часть считается законченным, если линия одна. Количество действий по изменению ширины ячейки — 2-4.
Вторая часть: так называемый метод половин.
Сначала определяется предельная точность подгонки, в данно случае 0.2мм.
Затем определяется шаг изменения, например, четверть от полученной в первой части ширины ячейки.
В цикле с условием «шаг (абсолютное значение, оно же модуль) больше, чем предел точности» повторяем следующие действия
Уменьшаем ширину ячейки на шаг до тех пор, пока количество линий не меняется (становится больше одной). Как только линий стало больше, шаг меняем на половину от предыдущего значения и меняем знак на противоположный. Уменьшаем (на самом деле увеличиваем, поскольку минус на минус равно плюс) ширину ячейки пока количество линий снова не меняется. Затем повторяем до тех пор, пока шаг не сравняется с предельной точностью.
После завершения цикла обязательно проверить количество линий, если больше одной — увеличить на последний шаг.
Количество итераций зависит от предельной точности и ширины колонки, но заведомо значительно меньше, чем при попытке увеличивать или уменьшать ширину на минимальный шаг.
 
  • Спасибо
Реакции: dim4an
только lines тут - не линии, а строки )
 
Собрав все знания во едино, решил реализовать все вот так
Код:
var maxLen = 0;
    var myLen = 0;
    var myLen1 = 0;
    var myLenSumm;
    var myT;
    var myCells;
    var table;
    var columnWidth = 0;
    var table = this.tables[0];
    var myCol = table.columns;
    var tableLeWidth = table.width;

    for (k=0;k<myCol.length;k++){
        maxLen = 0;     
        myCells = myCol[k].cells;
        columnWidth = myCol[k].width;
        var maxLen = 0;
        for(var i = 0; i < myCells.length; i++){
         
            while(myCells[i].overflows && tableLeWidth > myCol[k].width){
                myCol[k].width += columnWidth;
            } 

            var iteration = 0;
            myT = myCells[i].lines;
            while(myT.length > 1 && iteration < 2){ //если iteration > 2 значит в строке есть символы переноса строки
                    myCol[k].width = columnWidth * myT.length;
                    iteration++;
            } 

            myT = myCells[i].lines;
            if(myT.length == 1){
                try{
                    var ab = myT[0].insertionPoints[0].horizontalOffset - myCells[i].leftInset - myCells[i].rightInset;
                    myLen = myT[0].insertionPoints[-1].horizontalOffset - ab;
                }catch(e){alert("error " + e);}
                    try{ myLen1 = myT[0].insertionPoints[-2].horizontalOffset - ab; }catch(e2){myLen1 = 0;}
                if(myLen1 > myLen){myLen = myLen1;}
                if(myLen > maxLen) {maxLen = myLen};         
            }
        }
        if(maxLen > 0) {myCol[k].width = maxLen + 0.2;}

    }
}

но как бы не хотелось, с первого раза не заработало, и со второго тоже :(
проблема в этом участке кода. Если в ячейке текст не уместился, и "ушел в осадок", то я увеличиваю ширину колонки до тех пор, пока текст не уместится. Но значение myCells.overflows так и не меняется. Ширина колонки достигает максимально допустимого значения и выбрасывается исключение. пробовал также делать myCells.recompoce после увеличения ширины колонки, результат то же

Код:
        while(myCells[i].overflows){
                myCol[k].width += columnWidth;
            }
 

Вложения

  • тейбл.png
    тейбл.png
    15.6 КБ · Просм.: 865
Последнее редактирование:
Ширина колонки достигает максимально допустимого значения и выбрасывается исключение
Так а вытесненный текст в итоге показывается? Судя по результату — должен показаться, но не показывается. Странно, что recompose() не помог.
 
у Cells метода recompose() нет, он есть у Cell.
можно два раза подряд его вызвать, кстати.
 
Так а вытесненный текст в итоге показывается? Судя по результату — должен показаться, но не показывается. Странно, что recompose() не помог.
нет, не показывается. Двойной recompose() тоже не помог. Так же пытался сделать recompose() колонки. Тот же результат. Вообще странно кат то это все. Я так понял, первая ячейка которая owerflow, она всегда owerflow как на сколько бы мы не увеличивали величину колонки и не старались делать recompose(). Но вот что интересно, если первая ячейка и owerflow то последующие ячейки в столбце, при увеличении ширины колонки теряют это свойство, и текст в них умещается. Далее, каким то чудо образом и первая ячейка теряет это свойство.
 

Вложения

  • тбл2.jpg
    тбл2.jpg
    29.7 КБ · Просм.: 1 015
  • тбл1.jpg
    тбл1.jpg
    44.9 КБ · Просм.: 902
Пример в indd выложить можешь? Только не в rar пакуй, а то прокляну.
 
Пример в indd выложить можешь? Только не в rar пакуй, а то прокляну.
Да, конечно могу. В архиве 3 файлика, 1 файлик не обработанный скриптом, и 2 обработанных. В обоих есть ошибки в таблицах. Скачать можно от сюда http://yadi.sk/d/0MOyaE71BayKn. Прошу строго не судить, так как это еще далеко даже не бетта :)
 
Но значение myCells.overflows так и не меняется.
Провел пару экспериментов. Вот так работает гарантировано:
Код:
while(cell.overflows) {
    cell.columns[0].width = cell.columns[0].width*2;
    cell.recompose();
    cell.parent.recompose();
    cell.texts.everyItem().recompose();
    }
Вся сила в рекомпозитах всего, до чего можно дотянуться. Ибо реализация таблиц в ID почти такой же аццкий ад, как и реализация заякоренных объектов.
 
  • Спасибо
Реакции: dim4an
Провел пару экспериментов. Вот так работает гарантировано:
Код:
while(cell.overflows) {
    cell.columns[0].width = cell.columns[0].width*2;
    cell.recompose();
    cell.parent.recompose();
    cell.texts.everyItem().recompose();
    }
Вся сила в рекомпозитах всего, до чего можно дотянуться. Ибо реализация таблиц в ID почти такой же аццкий ад, как и реализация заякоренных объектов.

К сожалению у меня выдает тот же результат :(. Возможно это зависит от версии индизайна?
Работадатель вреде обещал голд поддержку от сапорта адоба, попробую обратится к ним.

p.s
Мне, как человеку ранее не кодившим для индизайна, весь индизайн показался аццким адом :).
 
Статус
Закрыто для дальнейших ответов.