Повторные показы окна ScriptUI

Есть еще одна "должна быть легкой" проблема. У меня есть окно ScriptUI, в котором мне нужно проверить, все ли поля заполнены. Идея состоит в том, что когда пользователь нажимает кнопку «ОК», сценарий проверяет, заполнены ли поля. Если нет, то он должен предупреждать пользователя об этом и снова показывать то же самое окно, пока он не сделать заполнить все это. Вот что у меня есть до сих пор:

var windowTitle = "Output Script v1.00 by Chris McGee";
var curDate = new Date();
var curDay = curDate.getDate();
var curMonth = curDate.getMonth() + 1;
var curYear = curDate.getYear() - 100;
var dateFormat = /^(0?[1-9]|1[012])[- \/.](0?[1-9]|[12][0-9]|3[01])[- \/.]\d\d$/;

var outputData = new Window("dialog", windowTitle);
    outputData.preferredSize = [337, 286];
    outputData.orientation = "stack";
    outputData.margins = 0;
    var stackGroup = outputData.add("group");
        stackGroup.margins = [0, 55, 0, 0];
        stackGroup.alignment = ["", "top"];
        stackGroup.alignChildren = ["", "top"];
        var textPanel = stackGroup.add("panel");
            textPanel.orientation = "row";
            textPanel.alignChildren = ["", "bottom"];
            var staticGroup = textPanel.add("group");
                staticGroup.orientation = "column";
                staticGroup.alignChildren = "right";
                staticGroup.spacing = 16;
                staticGroup.add("statictext", undefined, "&Order Number:");
                staticGroup.add("statictext", undefined, "&Ship Date:");
                staticGroup.add("statictext", undefined, "&Initials:");
                staticGroup.add("statictext", undefined, "Ove&rruns?");
            var editGroup = textPanel.add("group");
                editGroup.orientation = "column";
                editGroup.alignChildren = "left";
                var orderNumText = editGroup.add("edittext");
                    orderNumText.characters = 8;
                    orderNumText.active = true;
                    orderNumText.onChange = function ()
                    {
                        if (!/\b\d{6}\b/.test(orderNumText.text))
                        {
                            // If the entered text does not contain exactly 6 digits.
                            alert("The order number does not appear to conform to a standard order number.\n Please fix and try again.");
                        }
                    }
                var shipDateText = editGroup.add("edittext");
                    shipDateText.characters = 8;
                    shipDateText.onChange = function ()
                    {
                        if (dateFormat.test(shipDateText.text))
                        {
                            var enteredDate = shipDateText.text.match(/\b\d*\b/g);
                            var entMonth = parseInt(enteredDate[0]);
                            var entDay = parseInt(enteredDate[2]);
                            var entYear = parseInt(enteredDate[4]);
                            if (entYear < curYear || entYear > curYear + 1)
                            {
                                // If the entered year is older than the current year, or
                                // if the entered year is two or more years in the future.
                                alert("Invalid date entered.  Please fix.");
                            }
                            else if ((entYear > curYear && curMonth < 12) || entMonth > curMonth + 1)
                            {
                                // If the entered month is more than one month ahead, just verify that it is correct.
                                alert("Please verify that the entered date is correct before proceeding.");
                            }
                            else if ((entMonth < curMonth && curMonth < 12) || (entMonth == curMonth && entDay < curDay))
                            {
                                // If the entered date is within the same month, but on an earlier day, alert the user.
                                alert("Invalid date entered.  Please fix.");
                            }
                        }
                        else
                        {
                            alert("Date format not recognized.  Please try again.\nDate must be in the form of MM/DD/YY.");
                            shipDateText.text = "";
                        }
                    }
                var initialsText = editGroup.add("edittext");
                    initialsText.characters = 3;
                var overRunsBox = editGroup.add("checkbox");
        var buttonGroup = stackGroup.add("group");
            buttonGroup.orientation = "column";
            var okButton = buttonGroup.add("button", undefined, "OK", {name: "ok"});
            buttonGroup.add("button", undefined, "Cancel", {name: "cancel"});

var allFieldsFilled = false;
while (!allFieldsFilled)
{
    // If the user clicked "OK", then the contents get put into variables and the work begins on the document(s).
    if (outputData.show() == 1) {
        if (orderNumText.text == "" || shipDateText.text == "" || initialsText.text == "")
        {
            alert("Please fill out ALL fields.");
        }
        else
        {
            allFieldsFilled = true;
            var orderNum = orderNumText.text;
            var shipDate = shipDateText.text;
            var outputInitials = initialsText.text;
            var overRuns = overRunsBox.value;
        }
    } else {
        // If the user clicked "Cancel".
        exit();
    }
}

Проблема в том, что окно не появляется снова после предупреждающего сообщения. Почему это не так, и как я могу это исправить?

EDIT 23.09.2013: я добавил код, чтобы его можно было запустить. Я также заметил, что окно предупреждения о вводе текста появляется, даже если пользователь нажимает «Отмена».

EDIT 24.09.2013: я попытался реализовать идею @aristav, поэтому мой код теперь выглядит так:

var outputData = new Window("dialog", windowTitle);
    outputData.preferredSize = [337, 286];
    outputData.orientation = "stack";
    outputData.margins = 0;
    var stackGroup = outputData.add("group");
        stackGroup.margins = [0, 55, 0, 0];
        stackGroup.alignment = ["", "top"];
        stackGroup.alignChildren = ["", "top"];
        var textPanel = stackGroup.add("panel");
            textPanel.orientation = "row";
            textPanel.alignChildren = ["", "bottom"];
            var staticGroup = textPanel.add("group");
                staticGroup.orientation = "column";
                staticGroup.alignChildren = "right";
                staticGroup.spacing = 16;
                staticGroup.graphics.foregroundColor = staticGroup.graphics.newPen(outputData.graphics.PenType.SOLID_COLOR, [1, 1, 1], 1);
                staticGroup.add("statictext", undefined, "&Order Number:");
                staticGroup.add("statictext", undefined, "&Ship Date:");
                staticGroup.add("statictext", undefined, "&Initials:");
                staticGroup.add("statictext", undefined, "Ove&rruns?");
            var editGroup = textPanel.add("group");
                editGroup.orientation = "column";
                editGroup.alignChildren = "left";
                var orderNumText = editGroup.add("edittext");
                    orderNumText.characters = 8;
                    orderNumText.active = true;
                    orderNumText.onChange = function ()
                    {
                        if (!/\b\d{6}\b/.test(orderNumText.text))
                        {
                            // If the entered text does not contain exactly 6 digits.
                            alert("The order number does not appear to conform to a standard order number.\n Please fix and try again.");
                        }
                    }
                var shipDateText = editGroup.add("edittext");
                    shipDateText.characters = 8;
                    shipDateText.onChange = function ()
                    {
                        if (dateFormat.test(shipDateText.text))
                        {
                            var enteredDate = shipDateText.text.match(/\b\d*\b/g);
                            var entMonth = parseInt(enteredDate[0]);
                            var entDay = parseInt(enteredDate[2]);
                            var entYear = parseInt(enteredDate[4]);
                            if (entYear < curYear || entYear > curYear + 1)
                            {
                                // If the entered year is older than the current year, or
                                // if the entered year is two or more years in the future.
                                alert("Invalid date entered.  Please fix.");
                            }
                            else if ((entYear > curYear && curMonth < 12) || entMonth > curMonth + 1)
                            {
                                // If the entered month is more than one month ahead, just verify that it is correct.
                                alert("Please verify that the entered date is correct before proceeding.");
                            }
                            else if ((entMonth < curMonth && curMonth < 12) || (entMonth == curMonth && entDay < curDay))
                            {
                                // If the entered date is within the same month, but on an earlier day, alert the user.
                                alert("Invalid date entered.  Please fix.");
                            }
                        }
                        else
                        {
                            alert("Date format not recognized.  Please try again.\nDate must be in the form of MM/DD/YY.");
                            shipDateText.text = "";
                        }
                    }
                var initialsText = editGroup.add("edittext");
                    initialsText.characters = 3;
                var overRunsBox = editGroup.add("checkbox");
        var buttonGroup = stackGroup.add("group");
            buttonGroup.orientation = "column";
            var okButton = buttonGroup.add("button", undefined, "OK", {name: "ok"});
                okButton.onClick = function ()
                {
                    if (orderNumText.text == "" || shipDateText.text == "" || initialsText.text == "")
                    {
                        alert("Please fill out ALL fields.");
                    }
                    else
                    {
                        outputData.close();
                    }
                }
            var cancelButton = buttonGroup.add("button", undefined, "Cancel", {name: "cancel"});
                cancelButton.onClick = function () {$.writeln("Canceling."); outputData.close(); exit();}

outputData.show();

var orderNum = orderNumText.text;
var shipDate = shipDateText.text;
var outputInitials = initialsText.text;
var overRuns = overRunsBox.value;

Однако кнопка «Отмена» не отменяет. Это просто продолжается с кодом. Я думал, что директива exit(); полностью исключит его из сценария. Что я делаю неправильно?


person Sturm    schedule 20.09.2013    source источник
comment
можешь дать рабочий код?   -  person fabianmoronzirfas    schedule 21.09.2013
comment
Я думаю, что окно исчезает, потому что ExtendScript распознает кнопки с именем или меткой «ОК» как кнопки, закрывающие его. Попробуйте переименовать кнопку «ОК» и изменить ее метку на что-то вроде «Принять» и посмотрите, исчезнет ли ваше окно при нажатии на нее.   -  person ariestav    schedule 22.09.2013
comment
Я только что обновил код, чтобы его можно было запустить. @aristav: Пробовал, не получилось. Окно никогда не закрывается, и окно предупреждения никогда не появляется. Вот что я хочу, чтобы произошло: если пользователь не заполнил все поля, то окно должно закрыться (необязательно), отображается окно предупреждения, чтобы напомнить ему, что ему нужно заполнить все поля, а затем исходное окно показан снова, чтобы дать ему еще один шанс.   -  person Sturm    schedule 23.09.2013
comment
Если вы хотите, чтобы окно закрылось, а для имени кнопки или текстовой метки НЕ установлено значение OK, вам нужно вызвать метод .close() для окна, чтобы явно закрыть его. Итак, проверьте все поля. Если некоторые из них нуждаются в редактировании, отобразите предупреждение, сообщающее пользователю о необходимости выполнить свою работу. Когда они нажмут «ОК», появится окно. Если данные полей проходят проверку, предупреждение не отображается, а вызывается метод .close() для объекта окна.   -  person ariestav    schedule 23.09.2013
comment
@ariestav: Итак, вы предлагаете добавить обратный вызов .onClick() к кнопке «ОК», которая проверяет правильность? А также измените имя и метку этой кнопки на что-то отличное от «ОК», чтобы обратный вызов работал правильно?   -  person Sturm    schedule 23.09.2013
comment
@sturm Определенно добавьте обработчик события клика, да. Имя может остаться прежним, если вы зарегистрировали обработчик нажатия кнопки ok.   -  person ariestav    schedule 23.09.2013
comment
@ariestav: я добавил обратные вызовы `.onClick()' к обеим кнопкам, но теперь все стало еще хуже. Кнопка «Отмена» просто продолжает выполнение кода, а не выходит из сценария, как это должно быть.   -  person Sturm    schedule 24.09.2013
comment
@sturm вы используете метод .close () в обработчике отмены? В вашем коде кажется, что вы используете exit(); что не то же самое.   -  person ariestav    schedule 24.09.2013
comment
@sturm ах, я вижу, ты это делаешь. действительно ли диалог исчезает с экрана?   -  person ariestav    schedule 24.09.2013
comment
Да, метод .close() работает нормально; это определенно отклоняет диалог. Однако функция exit() не работает при нажатии кнопки «Отмена»; сценарий просто продолжает работать, когда я этого не хочу.   -  person Sturm    schedule 24.09.2013
comment
Откуда вы знаете, что он продолжает работать? Что для вас означает, что он работает? Я не уверен, что видел, как exit() использовался в какой-либо из разработок ExtendScript, которые я делал. Хост-приложение просто зависает?   -  person ariestav    schedule 24.09.2013
comment
В моей программе намного больше кода, чем вы видите выше. После нажатия кнопки «Отмена» (или кнопки «ОК», если все поля заполнены) выполняется остальная часть кода, которая включает отображение окна хода выполнения, когда некоторые документы открываются, обрабатываются, распечатываются, сохраняются и закрываются. InDesign не зависает, он просто продолжает выполнять остальную часть скрипта. Если exit(); является плохой практикой программирования, есть ли лучший способ отменить сценарий, если нажата эта кнопка «Отмена»?   -  person Sturm    schedule 25.09.2013
comment
Я решил пойти с другим подходом. Вместо того, чтобы проверять правильность при нажатии кнопки OK, я решил, что скрипт будет проверять действительность всякий раз, когда заполняется каждое из полей. Каждое поле имеет обратный вызов .onChange, который устанавливает состояние кнопки .enabled в true, если все поля заполнены. В противном случае кнопка остается неактивной (и недоступной для нажатия). Гораздо элегантнее, я думаю, чем пост-чек. Тем не менее, я все равно не прочь услышать решение этой проблемы, если у кого-то оно есть, просто для справки в будущем.   -  person Sturm    schedule 01.10.2013


Ответы (2)


Удалите exit() внутри onClick, и ошибка исчезнет:

cancelButton.onClick = function () {$.writeln("Canceling."); outputData.close();}
person Justin Putney    schedule 28.11.2013
comment
На самом деле я добавил больше кода к этой старой проблеме, чтобы она выполняла проверку перед нажатием кнопки OK. Он даже не активирует эту кнопку, пока все поля не будут заполнены в правильном формате. Я могу опубликовать это здесь, если вы думаете, что это будет полезно для других. - person Sturm; 02.12.2013
comment
Тебе решать. Если вы решили проблему, вероятно, было бы хорошо опубликовать решение для других. - person Justin Putney; 03.12.2013

Итак, самым простым решением проблемы было то, что практически не задокументировано. Оказывается, свойство .enabled можно использовать (почти) для любого объекта ScriptUI. Таким образом, я мог просто оставить кнопку OK отключенной, пока все поля не пройдут проверку. Мне понадобилась для этого отдельная функция, но она работает без нареканий:

function ifFieldsFilled ()
{
    if (orderNumText.text != "" && shipDateText.text != "" && initialsText.text != "" && dateValid)
    {
        return true;
    }
    else
    {
        return false;
    }
}

var curDate = new Date();
var curDay = curDate.getDate();
var curMonth = curDate.getMonth() + 1;
var curYear = curDate.getYear() - 100;
var dateFormat = /^(0?[1-9]|1[012])[- \/.](0?[1-9]|[12][0-9]|3[01])[- \/.]\d\d$/;
var dateValid = false;

var outputData = new Window("dialog", windowTitle);
    outputData.preferredSize = [337, 300];
    outputData.orientation = "stack";
    outputData.margins = 0;
    var stackGroup = outputData.add("group");
        stackGroup.margins = [0, 48, 0, 0];
        stackGroup.alignment = ["", "top"];
        stackGroup.alignChildren = ["", "top"];
        var textPanel = stackGroup.add("panel");
            textPanel.orientation = "row";
            textPanel.alignChildren = ["", "bottom"];
            var staticGroup = textPanel.add("group");
                staticGroup.orientation = "column";
                staticGroup.alignChildren = "right";
                staticGroup.spacing = 16;
                staticGroup.graphics.foregroundColor = staticGroup.graphics.newPen(outputData.graphics.PenType.SOLID_COLOR, [1, 1, 1], 1);
                staticGroup.add("statictext", undefined, "&Order Number:");
                staticGroup.add("statictext", undefined, "&Ship Date:");
                staticGroup.add("statictext", undefined, "&Initials:");
                staticGroup.add("statictext", undefined, "Ove&rruns?");
                staticGroup.add("statictext", undefined, "Digital &Print?");
            var editGroup = textPanel.add("group");
                editGroup.orientation = "column";
                editGroup.alignChildren = "left";
                var orderNumText = editGroup.add("edittext");
                    orderNumText.characters = 8;
                    orderNumText.active = true;
                    orderNumText.onChange = function ()
                    {
                        if (!/\b\d{6}\b/.test(orderNumText.text) && orderNumText.text != "")
                        {
                            // If the entered text does not contain exactly 6 digits.
                            alert("The order number does not appear to conform to a standard order number.\n Please fix and try again.");
                        }
                        okButton.enabled = ifFieldsFilled();
                    }
                var shipDateText = editGroup.add("edittext");
                    shipDateText.characters = 8;
                    shipDateText.onChange = function ()
                    {
                        if (dateFormat.test(shipDateText.text))
                        {
                            var enteredDate = shipDateText.text.match(/\b\d*\b/g);
                            var entMonth = parseInt(enteredDate[0]);
                            var entDay = parseInt(enteredDate[2]);
                            var entYear = parseInt(enteredDate[4]);
                            if (entYear < curYear || entYear > curYear + 1)
                            {
                                // If the entered year is older than the current year, or
                                // if the entered year is two or more years in the future.
                                alert("Invalid date entered.  Please fix.");
                                dateValid = false;
                            }
                            else if ((entYear > curYear && curMonth < 12) || entMonth > curMonth + 1)
                            {
                                // If the entered month is more than one month ahead, just verify that it is correct.
                                alert("Please verify that the entered date is correct before proceeding.");
                            }
                            else if ((entMonth < curMonth && curMonth < 12) || (entMonth == curMonth && entDay < curDay))
                            {
                                // If the entered date is within the same month, but on an earlier day, alert the user.
                                alert("Invalid date entered.  Please fix.");
                                dateValid = false;
                            }
                            else
                            {
                                // The date is completely valid.
                                dateValid = true;
                            }
                        }
                        else
                        {
                            alert("Date format not recognized.  Please try again.\nDate must be in the form of MM/DD/YY.");
                            shipDateText.text = "";
                        }
                        okButton.enabled = ifFieldsFilled();
                    }
                var initialsText = editGroup.add("edittext");
                    initialsText.characters = 3;
                    initialsText.onChanging = function ()
                    {
                        okButton.enabled = ifFieldsFilled();
                    }
                var overRunsBox = editGroup.add("checkbox");
                var digitalPrintBox = editGroup.add("checkbox");
        var buttonGroup = stackGroup.add("group");
            buttonGroup.orientation = "column";
            var okButton = buttonGroup.add("button", undefined, "OK", {name: "ok"});
                okButton.enabled = false;
            var cancelButton = buttonGroup.add("button", undefined, "Cancel", {name: "cancel"});

// If the user clicked "OK", then the contents get put into variables and the work begins on the document(s).
if (outputData.show() == 1) {
    var orderNum = orderNumText.text;
    var shipDate = shipDateText.text;
    var outputInitials = initialsText.text;
    var overRuns = overRunsBox.value;
    var digitalPrint = digitalPrintBox.value;
} else {
    // If the user clicked "Cancel".
    exit();
}

И код продолжается оттуда.

Таким образом, okButton сначала отключается, а затем проверяется каждый раз, когда пользователь заполняет поле или, в случае поля initialsText, пока пользователь что-то печатает. Кроме того, дополнительное условие && orderNumText.text != "", которое было добавлено в функцию .onChange() orderNumText, предназначено только для того, чтобы предотвратить отображение раздражающего диалогового окна с предупреждением, если пользователь нажмет [ESC] или нажмет кнопку Отмена перед заполнением этого текстового поля. .

Итак, это скрытое маленькое свойство .enabled было ключом, который помог мне решить эту проблему. Вроде очевидный ответ, оглядываясь назад. В любом случае, я надеюсь, что это будет полезно для всех, кто столкнулся с проблемой, подобной этой. Заботиться!

person Sturm    schedule 03.12.2013