У меня возникла проблема, аналогичная тем, о которых сообщалось как здесь, так и здесь, с небольшими изменениями в способе загрузки данных моей формы.
Решение, представленное во второй ссылке, по-видимому, решает мою проблему, но удаление эффектов масштабирования отображения/скрытия не требуется для правильного создания экземпляра CKEditor. Обязательно найдется гораздо лучшая альтернатива разрешению этого конфликта.
Моя проблема:
Когда я открываю свою страницу и нажимаю кнопку редактирования, появляется диалоговое окно jQueryUI, загружает свои данные через ajax, а затем я пытаюсь заменить текстовую область, добавленную в диалоговое окно, экземпляром CKEditor. При первой загрузке страницы диалог работает без сучка и задоринки. Я могу изменять данные в редакторе, сохранять данные формы и продолжать жить дальше. Однако, если я закрою диалоговое окно, а затем открою его снова, редактор больше не будет включен. Кнопки по-прежнему имеют эффекты наведения и кликабельны, но ничего не делают. Текстовая область редактора отключена и установлена на "style: visibility: hidden; display: none;"
. Почти вся информация, которую я могу найти по этой проблеме, была получена много лет назад, и исправления включают использование функций/методов, которые больше не существуют или не применимы.
Поток управления
Я открываю страницу, содержащую текстовую ссылку «Редактировать обновление», которая вызывает мою функцию Javascript openEditTicketUpdateDialog
.
function openEditTicketUpdateDialog(tup_id, url)
{
simplePost(null, url, new Callback
(
function onSuccess(data)
{
$('#editticketupdatedialog').dialog('option', 'buttons',
[
{
text: 'Save Edits',
click: function()
{
// Save the Update info
var formData = {
tup_update: CKEDITOR.instances.tup_update_edit.getData(),
tup_internal: +$('#tup_internal_edit').is(":checked"),
tup_important: +$('#tup_important_edit').is(":checked")
};
simplePost(formData, data['submitRoute'], new Callback
(
function onSuccess(data)
{
$('#update-' + tup_id).html(data.input['tup_update']);
$('#updateflags-' + tup_id).html(data.flags);
$('#editticketupdatedialog').dialog('close');
},
function onFail(errors)
{
console.log(errors);
}
));
}
},
{
text: 'Cancel',
click: function()
{
$(this).dialog("close");
}
}
]);
$('#editticketupdatedialog').dialog('option', 'title', data['title']);
$('#editticketupdatedialog').html(data['view']);
$('#editticketupdatedialog').dialog('open');
destroyEditor('tup_update_edit');
console.log('CKEDITOR.status: ' + CKEDITOR.status);
createEditor('tup_update_edit');
},
function onFail(errors)
{
console.log(errors);
}
));
}
Эта функция использует три вспомогательные функции: simplePost
, destroyEditor
и createEditor
.
function simplePost(data, url, callback)
{
post(data, url, true, false, callback);
}
function createEditor(name)
{
console.log('Create editor: ' + name);
console.log('Current Instance: ');
console.log(CKEDITOR.instances.name);
if (CKEDITOR.status == 'loaded')
{
CKEDITOR.replace(name,
{
customConfig: '/js/ckeditor/custom/configurations/standard_config.js'
});
}
else
{
CKEDITOR.on('load', createEditor(name));
CKEDITOR.loadFullCore && CKEDITOR.loadFullCore();
}
console.log('After instance created: ');
var instance = CKEDITOR.instances.name;
console.log(instance);
}
function destroyEditor(name)
{
console.log('Destroy editor: ' + name);
console.log('Current Instance: ');
console.log(CKEDITOR.instances.name);
if (CKEDITOR.instances.name)
{
console.log('Instance exists - destroying...');
CKEDITOR.instances.name.destroy();
$('#' + name).off().remove();
}
console.log('After instance removed: ');
var instance = CKEDITOR.instances.name;
console.log(instance);
}
Этот метод создания экземпляра CKEditor взят из здесь. Этот метод уничтожения экземпляра CKEditor взят из здесь.
Как видите, openEditTicketUpdateDialog
запускает AJAX-вызов моей функции getEditUpdateForm
через маршруты Laravel.
public function getEditUpdateForm($tup_id, $update_number)
{
$update = Update::find($tup_id);
$data = [
'title' => 'Editing update #' . $update_number . ' of ticket #' . $update->tup_ticket,
'view' => View::make('tickets.ticketupdate-edit')
->with('update', $update)
->render(),
'submitRoute' => route('tickets/update/submit', $tup_id)
];
return Response::json(array('status' => 1, 'data' => $data));
}
Отсюда возвращается статус 1 и вызывается функция onSuccess
. Я пытался добавить вызовы создания/удаления перед вызовом $('#editticketupdatedialog').dialog('open');
, но безрезультатно. Я также пробовал несколько других решений, которые я обнаружил, которые включают взломанные реализации функций и атрибутов Dialog jQueryUI: _allowInteraction
и moveToTop
. Первоначально мне удалось решить эту проблему в первый раз, когда она возникла, вызвав эту функцию перед выполнением CKEDITOR.replace
:
function enableCKEditorInDialog()
{
$.widget( "ui.dialog", $.ui.dialog, {
/**
* jQuery UI v1.11+ fix to accommodate CKEditor (and other iframed content) inside a dialog
* @see http://bugs.jqueryui.com/ticket/9087
* @see http://dev.ckeditor.com/ticket/10269
*/
_allowInteraction: function( event ) {
return this._super( event ) ||
// addresses general interaction issues with iframes inside a dialog
event.target.ownerDocument !== this.document[ 0 ] ||
// addresses interaction issues with CKEditor's dialog windows and iframe-based dropdowns in IE
!!$( event.target ).closest( ".cke_dialog, .cke_dialog_background_cover, .cke" ).length;
}
});
}
После обновления до Laravel 5 и внесения нескольких других изменений на стороне сервера это исправление больше не работает. Мне удалось решить мою проблему, удалив свойства отображения/скрытия из моего диалогового окна. Я бы очень предпочел не удалять эти свойства, так как половина аргументов в пользу наличия диалога — это эстетика анимации. Вот моя инициализация диалога.
$('#editticketupdatedialog').dialog({
modal: true,
draggable: false,
minWidth: 722,
autoOpen: false,
show:
{
effect: "scale",
duration: 200
},
hide:
{
effect: "scale",
duration: 200
},
closeOnEscape: true
});
Когда у меня включены эти анимации, в первый раз, когда я использую диалог, он работает отлично. Во второй раз я получаю ошибку TypeError: this.getWindow(...).$ is undefined - ckeditor.js:83:18
в консоли JS, которая относится к этой строке:
function(a)
{
var d = this.getWindow().$.getComputedStyle(this.$,null);
return d ? d.getPropertyValue(a) : ""
}
Подведение итогов
Моя главная цель здесь — найти решение этой проблемы, не удаляя анимацию диалогового окна jQueryUI. Я не уверен, на кого указать пальцем, так как я действительно не могу определить, связана ли проблема с CKEditor, jQueryUI или моей реализацией.