jQuery UI, AJAX и CKEditor - CKEditor загружается только в первый раз

У меня проблема, похожая на проблемы, о которых сообщалось и здесь, и здесь, только с несколькими изменениями в том, как загружаются данные моей формы.

Решение, представленное во второй ссылке, по-видимому, решает мою проблему, но удаление эффектов масштабирования "показать / скрыть" не требуется для правильного создания экземпляра 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 и внесения нескольких других изменений на стороне сервера это исправление больше не работает. Мне удалось решить мою проблему, удалив свойства show/hide из моего диалога. Я бы очень предпочел не удалять эти свойства, так как половина аргументов в пользу диалога - это эстетика анимации. Вот мой диалог инициализации.

$('#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 Dialog. Я не уверен, на кого указывать, поскольку действительно не могу определить, кроется ли проблема в CKEditor, jQueryUI или в моей реализации.

1 ответ

Я наконец нашел решение, которое работает в моем случае. losnir обновил устаревшее решение для поста здесь, и добавление функции open к моей инициализации диалога решило мою проблему.

Моя инициализация выглядит следующим образом:

$('#editticketupdatedialog').dialog({
    modal: true,
    draggable: false,
    minWidth: 722,
    autoOpen: false,
    show:
    {
        effect: "scale",
        duration: 200
    },
    hide:
    {
        effect: "scale",
        duration: 200
    },
    closeOnEscape: true,
    open: function()
    {
        $(this).parent().promise().done(function ()
        {
            destroyEditor('tup_update_edit');

            console.log('CKEDITOR.status: ' + CKEDITOR.status);
            createEditor('tup_update_edit');
        });
    }
});
Другие вопросы по тегам