Как я могу заставить имена действий отмены / повтора NSUndoManager работать правильно?

Я изучаю Какао, а я ' он получил отмену, чтобы работать без особых проблем. Но метод setActionName: меня озадачивает. Вот простой пример: игрушечное приложение, окна которого содержат одну текстовую метку и две кнопки. Нажмите кнопку «Вкл», и на этикетке появится надпись «Вкл». Нажмите кнопку Off, и метка изменится на «Off». Вот два соответствующих метода (единственный код, который я написал для приложения):

-(IBAction) turnOnLabel:(id)sender
{
    [[self undoManager] registerUndoWithTarget:self selector:@selector(turnOffLabel:) object:self];
    [[self undoManager] setActionName:@"Turn On Label"];
    [theLabel setStringValue:@"On"];
}

-(IBAction) turnOffLabel:(id)sender
{
    [[self undoManager] registerUndoWithTarget:self selector:@selector(turnOnLabel:) object:self];
    [[self undoManager] setActionName:@"Turn Off Label"];
    [theLabel setStringValue:@"Off"];
}

Вот чего я ожидал:

  • Я нажимаю кнопку «Вкл.»
  • Метка меняется на «Вкл.»
  • В окне редактирования в меню есть пункт «Отменить включение метки»
  • Я щелкаю этот пункт меню
  • Метка меняется на «Выкл.»
  • В меню «Правка» находится пункт «Вернуть метку включения»

Фактически , все эти вещи работают так, как я ожидал, кроме последнего. Пункт в меню «Правка» гласит «Вернуть выключить ярлык», а не «Вернуть ярлык включения». s функция отмены. Сразу же меня не беспокоит кроссбраузерность; Меня волнует только Chrome. Мой подход выглядит примерно так:

$('.editable').live('paste', function()
{
    var $this = $(this);

    //more code here to remember caret position, etc

    $('#clipboard').val('').focus(); //put the focus in the hidden textarea so that, when the paste actually occurs, it's auto-sanitized by the textarea

    setTimeout(function() //then this will be executed immediately after the paste actually occurs
    {
        $this.focus();
        document.execCommand('insertHTML', true, $('#clipboard').val());
    });
});

Итак, это работает - я могу вставить что угодно, и это преобразовано в обычный текст, прежде чем вводить мое поле contentEditable , но если я попытаюсь отменить после вставки:

  • Первая отмена отменяет вставку.
  • Вторая отмена пытается отменить изменения в #clipboard , перемещая фокус с моего contentEditable .

Я пробовал все Я могу придумать, как заставить браузер не пытаться отменить изменения в #clipboard - переключение отображения: нет , когда он не используется активно, переключение только для чтения и отключено состояние, уничтожение его в конце и воссоздание в начале события выше, различные другие взломы - но, похоже, ничего не работает.

Это ужасный подход к дезинфекции? Это первое, с чем мне удалось по-настоящему поработать - попытка очистить разметку после вставки не сработала, поскольку есть некоторые вещи (целые HTML-документы), которые при вставке приводят к сбою браузера, что Я бы хотел избежать.

Есть ли способ сделать #clipboard не отключаемым, или какие-либо другие предложения, как заставить это работать?

Править

Мне удалось улучшить немного, добавив строку

$('#clipboard').val('');

сразу после строки execCommand . Похоже, что это полностью нейтрализует отмену: курсор больше не покидает поле contentEditable , но ничего не отменяется вообще. Небольшое улучшение, но я все еще ищу подходящее решение.

10
задан Ian Henry 24 February 2011 в 06:51
поделиться