使用$ .load()异步问题的jQuery执行顺序(bootstrap模式)

时间:2014-07-06 18:35:29

标签: javascript jquery html twitter-bootstrap bootstrap-modal

我对jQuery操作顺序有一个奇怪的问题。下面的代码在ie9&中完美地执行。 IE10。在ie11,firefox和chrome中,它根本不起作用。它将执行并打开新窗口,但load()不会触发。我可以在事件链中发出警报,而load()在firefox和ie11中运行...在chrome中它仍然不会运行load()。

起初,我认为加载的目标尚未添加到DOM中,并且警报创建的暂停使其有时间被创建。我在完全相同的位置添加了一个睡眠计时器来测试该理论 - 它不起作用,并且定时器的设置时间并不重要。

对这个问题的任何想法都会有所帮助。谢谢你们和gals!

    function openWindow(id, which, windowOptions) {
        $('<div>')
        .attr('id', 'GenericWindow')
        .addClass('modal hide fade')
        .html('<div class="modal-header"><button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button><h3 id="WindowHeader">Loading...</h3>'
        + '</div><div id="divWindowContent" class="modal-body">Content!</div><div id="WindowButtons" class="modal-footer"><input type="button" id="btnWindowCancel" value="Cancel" class="btn" data-dismiss="modal" aria-hidden="true" />'
        + '<input type="button" id="btnWindowSave" value="Save" class="btn btn-info" />')
        .modal({"keyboard":"true"})
        .on('hidden', function (e) {
            var src = $(e.target);
            if (!src.hasClass('popover-link')) {
                $('#GenericWindow').remove();
                clearErrors();
            }
        });
        if (!windowOptions) {
            //THIS IS THE ALERT.
            alert('huh');

            var link = '@Url.Action("replace", "Operations")'
            link = link.replace("replace", which);

            $('#divWindowContent').load(link, { id: id }, function (response, status, xhr) {
                if (status == "error") {
                    var msg = "Error loading details : ";
                    $('#divWindowContent').html(msg + xhr.status + " " + xhr.statusText);
                }
            });
        }
        else {
            if (windowOptions.action) {
                var action = windowOptions.action;
                    var link = '@Url.Action("view", "controller", new { Area = "MvcMembership" })';
                if (!$.isNull(action.area))
                    link = link.replace("MvcMembership", action.area);
                else
                    link = link.replace("/MvcMembership", "");
                link = link.replace("view", action.view);
                link = link.replace("controller", action.controller);

                $('#divWindowContent').load(link, action.values, function (response, status, xhr) {
                    if (status == "error") {
                        var msg = "Error loading details : ";
                        $('#divWindowContent').html(msg + xhr.status + " " + xhr.statusText);
                    }
                });
            }
            else {
                $('#divWindowContent').html(windowOptions.text);                    
            }
            $('#WindowHeader').html(windowOptions.title);
            if (windowOptions.hideButtons) {
                $('#WindowButtons').remove();
                $('#GenericWindow .close').remove();
            }
            $('#GenericWindow').css('width', windowOptions.width);
            $('#GenericWindow').css('height', windowOptions.height);
        }
    }
编辑:我应该注意,如果您在打开新模态之前使用函数关闭页面上的任何打开模态,则appendTo('body')不起作用。您必须使用“创建变量”解决方案。值得注意的是,创建变量的速度要快得多,尤其是在第一个模态打开后。

2 个答案:

答案 0 :(得分:2)

选择器无法正确捕捉您动态创建的窗口,直到您将其添加为页面中的元素(无论如何都是Chrome)。

要解决此问题,您可以将GenericWindow附加到body并在关闭窗口时将其关闭。

或者将元素存储在变量中并调用变量上的负载。

使用jsfiddle中的Chrome工作示例:

解决方案1:http://jsfiddle.net/4c3hu/

$(document).ready(function(){
    openWindow('blerg', 'test', null);
});


function openWindow(id, which, windowOptions) {
        $('<div>')
        .attr('id', 'GenericWindow')
        .addClass('modal hide fade')
        .html('<div class="modal-header"><button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button><h3 id="WindowHeader">Loading...</h3>'
    + '</div><div id="divWindowContent" class="modal-body">Content!</div><div id="WindowButtons" class="modal-footer"><input type="button" id="btnWindowCancel" value="Cancel" class="btn" data-dismiss="modal" aria-hidden="true" />'
    + '<input type="button" id="btnWindowSave" value="Save" class="btn btn-info" />')
        .modal({"keyboard":"true"})
        .appendTo('body')
        .on('hidden', function (e) {
            var src = $(e.target);
            if (!src.hasClass('popover-link')) {
                $('#GenericWindow').remove();
                clearErrors();
            }
        });
        if (!windowOptions) {
            //THIS IS THE ALERT.
            console.log('huh');

            var link = '@Url.Action("replace", "Operations")'
            link = link.replace("replace", which)
            link = '/echo/html/'
            console.log(link);
            $('#divWindowContent').load(link, { id: id }, function (response, status, xhr) {
                console.log('after load');
                if (status == "error") {
                    var msg = "Error loading details : ";
                    $('#divWindowContent').html(msg + xhr.status + " " + xhr.statusText);
                }
            });
        }
        else {
            if (windowOptions.action) {
                var action = windowOptions.action;
                var link = '@Url.Action("view", "controller", new { Area = "MvcMembership" })';
                if (!$.isNull(action.area))
                    link = link.replace("MvcMembership", action.area);
                else
                    link = link.replace("/MvcMembership", "");
                link = link.replace("view", action.view);
                link = link.replace("controller", action.controller);

                $('#divWindowContent').load(link, action.values, function (response, status, xhr) {
                    if (status == "error") {
                        var msg = "Error loading details : ";
                        $('#divWindowContent').html(msg + xhr.status + " " + xhr.statusText);
                     }
                });
            }
            else {
                $('#divWindowContent').html(windowOptions.text);                    
            }
            $('#WindowHeader').html(windowOptions.title);
            if (windowOptions.hideButtons) {
                $('#WindowButtons').remove();
                $('#GenericWindow .close').remove();
            }
            $('#GenericWindow').css('width', windowOptions.width);
            $('#GenericWindow').css('height', windowOptions.height);
        }
    }

解决方案2:http://jsfiddle.net/4c3hu/1/

$(document).ready(function(){
    openWindow('blerg', 'test', null);
});


function openWindow(id, which, windowOptions) {
        var $elem = $('<div>')
        .attr('id', 'GenericWindow')
        .addClass('modal hide fade')
        .html('<div class="modal-header"><button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button><h3 id="WindowHeader">Loading...</h3>'
        + '</div><div id="divWindowContent" class="modal-body">Content!</div><div id="WindowButtons" class="modal-footer"><input type="button" id="btnWindowCancel" value="Cancel" class="btn" data-dismiss="modal" aria-hidden="true" />'
        + '<input type="button" id="btnWindowSave" value="Save" class="btn btn-info" />')
        .modal({"keyboard":"true"})
        .on('hidden', function (e) {
            var src = $(e.target);
            if (!src.hasClass('popover-link')) {
                $('#GenericWindow').remove();
                clearErrors();
            }
        });
        if (!windowOptions) {
            //THIS IS THE ALERT.
            console.log('huh');

            var link = '@Url.Action("replace", "Operations")'
            link = link.replace("replace", which)
            link = '/echo/html/'
            console.log(link);
            $elem.load(link, { id: id }, function (response, status, xhr) {
                console.log('after load');
                if (status == "error") {
                    var msg = "Error loading details : ";
                    $('#divWindowContent').html(msg + xhr.status + " " + xhr.statusText);
                }
            });
        }
        else {
            if (windowOptions.action) {
                var action = windowOptions.action;
                var link = '@Url.Action("view", "controller", new { Area = "MvcMembership" })';
                if (!$.isNull(action.area))
                    link = link.replace("MvcMembership", action.area);
                else
                    link = link.replace("/MvcMembership", "");
                link = link.replace("view", action.view);
                link = link.replace("controller", action.controller);

                $elem.load(link, action.values, function (response, status, xhr) {
                    if (status == "error") {
                        var msg = "Error loading details : ";
                        $('#divWindowContent').html(msg + xhr.status + " " + xhr.statusText);
                    }
                });
            }
            else {
                $('#divWindowContent').html(windowOptions.text);                    
            }
            $('#WindowHeader').html(windowOptions.title);
            if (windowOptions.hideButtons) {
                $('#WindowButtons').remove();
                $('#GenericWindow .close').remove();
            }
            $('#GenericWindow').css('width', windowOptions.width);
            $('#GenericWindow').css('height', windowOptions.height);
        } 
    }

答案 1 :(得分:2)

您的问题不在于.load()函数,而在于.modal()向DOM添加新元素的方式。整个浏览器并不一致。

此外,jQuery的选择器只能查看已附加到DOM的内容。

这是一个说明问题的小提琴:

http://jsfiddle.net/4NdNQ/

这将在某些浏览器中打印0, 1,在其他浏览器中打印1, 1

您要做的是保持对父级的引用并搜索其子级而不是所有DOM元素。下面的小提琴说明了这一点,它总是会在任何浏览器中找到包含的<div>

http://jsfiddle.net/4NdNQ/1/

这就是魔术发生的原因:

var container = $('<div>').html('<div id=myElementId></div>');
// container now only exists in the script stack, it's not present in the DOM
$("#myElementId"); // <- this selects nothing
container.find("#myElementId").load( /* parameters */); // <- this now works

ED:@ YanBrunet的答案也解释了这个问题,但我会把它作为解决问题的另一种方法 - 因为这是一个较小的变化