Используя отмену при редактировании

Можно отменить высокоуровневые операции редактирования веб-контента — редактирования, сделанные программно и пользователем — не пишущий дополнительного кода. Однако, если Вы программно изменяете Объектную модель документа (DOM), необходимо записать дополнительный код для создания тех операций невыполнимыми.

Например, можно отменить высокоуровневые операции программно следующим образом:

    // Delete content
    [webView deleteSelection];
 
    // Restore it
    [[webView undoManager] undo];

Однако не столь просто отменить операцию DOM. Это не достаточно хорошо для возврата DOM эквивалентному состоянию — это должно быть точно, как это было первоначально. Например, Вы не можете только отменить удаленный текст путем создания нового узла и вставки его в старое расположение. Ссылки между узлами должны быть точно, поскольку они прежде удаляли текст.

Один подход должен сохранить удаленные объекты так, чтобы у Вас все еще была копия. Например, Вы могли бы сохранить удаленный узел DOM прежде, чем удалить его из дерева следующим образом:

 DOMNode *containerNode = [self containerNode];
 
    // Must keep a copy before removing from the document
    deletedNode = [containerNode lastChild];
 
    // Now remove
    [containerNode removeChild:deletedNode];
 
    // Make undoable
    [[webView undoManager] registerUndoWithTarget:self selector:@selector(undoAction) object:self];

Можно тогда реализовать undoAction возвратить DOM его исходному состоянию:

- (void)undoAction
{
    DOMNode *containerNode = [self containerNode];
 
    // Put the node back
    [containerNode appendChild:deletedNode];
 
    // Make redoable
    [[webView undoManager] registerUndoWithTarget:self selector:@selector(redoAction) object:self];
}

redoAction просто удаляет сохраненный узел снова следующим образом:

 
 
- (void)redoAction
{
    DOMNode *containerNode = [self containerNode];
 
    // Take node out again
    [containerNode removeChild:deletedNode];
 
    // Make undoable
    [[webView undoManager] registerUndoWithTarget:self selector:@selector(undoAction) object:self];
}