Утечки памяти в диалоговом окне jQuery-UI - PullRequest
5 голосов
/ 19 января 2010

Я работаю с IE7 и некоторыми диалоговыми окнами jQuery и сталкиваюсь с утечкой около 6 мг на каждое открытое диалоговое окно. Я предполагаю, что это связано с замыканиями, но пока все, что я сделал для их удаления, не помогло. На данный момент, я думаю, я позаботился обо всех замыканиях, кроме функции обратного вызова, которую я передаю, но она все равно пропускает 6 мегабайт даже после закрытия и удаления диалога. Соответствующий исходный код:

function DialogDestroyAndRemove(event) {
    $(event.target).dialog("destroy").remove();
}

function CallbackAndCloseDialog(event) {
    if (event.data.callback != undefined) {
        event.data.callback(event.data.callbackResponse);
    }
    $("#" + event.data.dialogId).unbind('dialogbeforeclose').dialog('close');
}

// alert dialog modal with ok button
function AlertDialog(dialogTitle, dialogText, callbackFunction) {
    // dynamically generate and add a div so we can create the pop-up
    $('body').append("<div id=\"alertDialog\" style=\"display:none;\" title=\"" + dialogTitle + "\">" + dialogText + "</div>");

    // define/configure the modal pop-up
    $("#alertDialog").dialog({
        draggable: false,
        resizable: false,
        modal: true,
        autoOpen: true,
        open: function() {
            $("#alertDialog").parents('.ui-dialog-buttonpane button:eq(0)')
            .focus() //focus so the button is highlighted by default
            .bind('click', {
                callback: callbackFunction,
                callbackResponse: 'OK',
                dialogId: 'alertDialog'
            }, CallbackAndCloseDialog);
        },
        overlay: { backgroundColor: '#000', opacity: 0.5 },
        buttons: { 'OK': function() { } }
    }).bind('dialogbeforeclose', function(event, ui) {
        // Close (X) button was clicked; NOT the OK button
        if (callbackFunction != undefined) {
            callbackFunction('cancel');
        }
        callbackFunction = null;
    }).bind('dialogclose', DialogDestroyAndRemove);
}

Одна вещь, которую я сделал выше, это то, что я не уверен, что это необходимо, вместо того, чтобы определять обратный вызов для кнопки ОК, когда она определена (и, следовательно, иметь замыкание, так как она ссылается на обратный вызов), чтобы определить его с помощью диалог открыт. Я надеялся, что возможность передать обратный вызов как часть данных событию click может помочь удалить замыкание.

Есть идеи, что еще я могу изменить, чтобы избавиться от этой утечки?

Ответы [ 2 ]

5 голосов
/ 20 января 2010

Это на самом деле вызвано тем, как фреймворк пользовательского интерфейса jQuery справляется с выделением фона при отображении модального окна. Если я удалю modal = true и атрибуты оверлея, утечка памяти уменьшится до ~ 100k.

Чтобы обойти это, мне пришлось сделать диалог без модальной опции, а затем добавить сам div на страницу (фиксированная позиция top, left, bottom, right все 0 с чередующимся серым пикселем, а затем прозрачным фоном пикселя) и показать и скрыть это с помощью zindex прямо под диалогом.

Хотя это не идеально (модальное наложение по умолчанию было красивым и плавным), это лучше, чем утечка большого количества памяти за всплывающее диалоговое окно.

1 голос
/ 01 февраля 2010

Надеюсь, это поможет, я создал расширение для этой проблемы, в котором я использую плагин jQuery tools (flowplayer), когда modal = true для диалогового окна jQuery UI.

Я бы включил код fol http://jsfiddle.net/yZ56q/lowing в отдельный файл .js и обязательно включил плагин предоставления инструментов jQuery с этого сайта ... http://flowplayer.org/tools/download.html.

(function($) {
    var _init = $.ui.dialog.prototype._init;
    $.ui.dialog.prototype._init = function() {
        var self = this;
        _init.apply(this, arguments);

        // Remove the default modal behavior and exhibit the new one
        if (self.options.modal) {
            self.options.modal = false;
            self.options.isModal = true;
        }

        this.uiDialog.bind('dialogopen', function(event, ui) {
            if (self.options.isModal) {
                if ($(this).expose == null)
                    window.alert("Dialog box depends on the expose plugin to be modal. Please include the jquery tools Javascript include.");
                else {
                    $(this).expose({ opacity: 0.3
                            , color: '#CCCCCC'
                            , loadSpeed: 0
                            , closeSpeed: 0
                            , closeOnClick: false
                            , closeOnEsc: false
                            , api: true
                    }).load();
                }
            }
        });

        this.uiDialog.bind('dialogfocus', function(event, ui) {
            if (self.options.isModal) {
                $(this).css('z-index', '9999');
            }
        });

        this.uiDialog.bind('dialogclose', function(event, ui) {
            if (self.options.isModal) {
                if ($(this).expose != null) {
                    $(this).expose({ api: true }).close();
                }
            }
        });
    };

        $.ui.dialog.defaults.isModal = false;
})(jQuery);
...