使用jQuery和Ajax.BeginForm使用“Loading ...”spinner.gif将div居中

时间:2010-12-16 13:33:26

标签: jquery css asp.net-mvc ajax

设置

我设计了一个非常易于使用的MVC向导。蛋糕上的樱桃是一个旋转器gif,当我改变向导步骤时会出现。无论浏览器窗口的大小如何,我都希望它以页面为中心。

您可以在以下位置查看此示例:

Sample Wizard

请不要完成巫师,除非你有嗜好......

问题

问题是,我有一个居中的CSS布局,由以下规则控制:

#PageContainer
{
    position:relative;
    width:800px;
    left:50%;   
    margin:0px 0px 0px -400px;
    text-align:left;
}

这个规则似乎与使用spinner gif将div居中的jquery代码严重交互。即,它不是中心。

守则

我的MVC表单代码是:

    @using (Ajax.BeginForm(Model.Step.ActionName, 
             null, 
             new AjaxOptions { UpdateTargetId = "wizardStep", OnBegin="isValid", LoadingElementId="PleaseWait" }, 
             new {@name="wizardForm", @id="wizardForm" } ))
        { 
        @* do ajax stuff, see my "Loading... panel below *@

        <div id="PleaseWait" style="display:none;">
            Please Wait...
        </div>
        } 

jQuery代码是:

<script type="text/javascript">
        jQuery.fn.center = function () {
            this.css("position", "absolute");
            this.css("top", ($(window).height() - this.height())/ 2 + $(window).scrollTop() + "px");
            this.css("left", ($(window).width() - this.width()) / 2 + $(window).scrollLeft() + "px");
            return this;
        }
        });
        function isValid() {
            $('#PleaseWait').center();
            if (true) // In case i whant to return true
            {
                return true;
            }
            else // I whant to return false
            {
                $('#PleaseWait').hide(); // Manually hide the LoadingElementId
                return false;
            }
        }   
</script>

我的分析

由于jQuery代码将div面板设置为具有绝对位置,因此它具有相对于没有位置static(默认值)的第一个父项的绝对位置。

因此,由于用于居中页面的边距黑客,jQuery计算中存在一些令苹果推车感到不安的东西。

即:

jQuery计算基于窗口的大小,但#PleaseWait面板的位置相对于#PageContainer div定位(此div是布局的一部分)。显然,这是两个截然不同的事情。因此,我认为我会找出从#PleaseWait div的顶部和左侧计算中减去的常数值。

然而,结果是不可预测的,我现在太迷惑了解。救命啊!

任何帮助都非常感激。

JOB DONE!:

问题排序。看看Jim接受的想法答案,我的后续答案是否完整实施。

3 个答案:

答案 0 :(得分:3)

AW,

不知道为什么这不会发生在我身上。您可以使用jquery在主模板中克服整个附加div的问题。 la:

function initSpinnerFunction(){
    // this would be you first line (i.e. prepend to body)
    $("body").prepend("<div id ='PleaseWait' style='display:none;'></div>");
    // OR if you want a jquery reference to the newly 
    // created div for whatever reason
    var newDiv = $("<div id ='PleaseWait' style='display:none;'></div>")
                 .prependTo('body');
    // then do rest of normal jquery stuff such as making div visible etc...
}

function exitSpinnerFunction(){
    // normal spinner exit stuff followed by final line 
    // which removes the pleasewait div from the DOM
    $("body").remove("#PleaseWait");
    // OR
    $("#PleaseWait").remove();
}

它可能适合也可能不适合,但肯定会将其限制为仅主动调用微调器的页面....

答案 1 :(得分:3)

你有没有想过使用BlockUI,似乎是一个很好的候选人。我之前在其中一个项目中使用过它,它非常好。

答案 2 :(得分:2)

Hack 1:

我已经“解决”了这个问题,因为我已将#PleaseWait div移到了网站主视图的最顶层。这样,#PageContanier及其相对位置就不会与设置进行交互。它现在有效。

缺点是现在app中的每个页面都有这个div(style =“display:none;”)。只有其中一些人会需要它。

黑客2:

对Hack 1的改进是在body标签下创建一个Content占位符。这样,从您需要它的页面,您可以注入任何div,您需要在页面上设置一个居中的面板。

这消除了不使用面板的页面中的冗余,并为您提供了很大的灵活性。但是,缺点是每次必须编写代码。不完全是DRY,所以......

看妈妈,没有黑客!:

感谢Jim的建议(见接受的答案),我已经解决了这个问题。不再需要黑客攻击。

我可以使用纯jQuery解决方案,如下所示(如果禁用javascript,没有任何反应,这很好)。

所以:

我创建了一个Utilities.js文件并在其中添加了以下函数:

    function initSpinnerFunction() {
        $("body").prepend("<div id ='PleaseWait' style='display:none;'>Please wait...</div>");.
    }
    // Add the jQuery center() method...
    jQuery.fn.center = function () {
                this.css("position", "absolute");
                this.css("top", ($(window).height() - this.height())/ 2 + $(window).scrollTop() + "px");
                this.css("left", ($(window).width() - this.width()) / 2 + $(window).scrollLeft() + "px");
                return this;
            }
            });

在我的wizard.aspx视图中,我输入了以下jQuery代码:

    $(document).ready(function () {
                initSpinnerFunction();            
            });

            function isValid() {
                $('#PleaseWait').center();
                if (true) // In case I want to return true
                {
                    return true;
                }
                else // I want to return false
                {
                    $('#PleaseWait').hide(); // Manually hide the LoadingElementId
                    return false;
                }
            }

如前所述,isValid()函数在我的MVC AJAX表单中使用(见下文)。

MVC Ajax表单不会改变。即:

@using (Ajax.BeginForm(Model.Step.ActionName, 
             null, 
             new AjaxOptions { UpdateTargetId = "wizardStep", OnBegin="isValid", LoadingElementId="PleaseWait" }, 
             new {@name="wizardForm", @id="wizardForm" } ))
        { 
        @* do ajax stuff, see my "Loading... panel below *@
        }

如果禁用了javascript,解决方案仍然有效。 spinner gif没有显示哪个是正确的行为,因为没有异步请求,只是页面刷新。

使用这个小框架,不再需要上面详述的hack:只有明确请求它的页面才有PleaseWait div。

为了设置PleaseWait div的样式,我使用了:

<style type="text/css">
        #PleaseWait
        {
            z-index: 2000;
            padding:6px;
            padding-left:40px;
            background:#F2E8BC url("../Images/Shared/spinner.gif") no-repeat 6px center;
            width:200px;
            height:80px;
            -webkit-border-radius: 10px;
            -moz-border-radius: 10px;
            border:4px solid #666;
            font-weight:bold;
        }
    </style>

此规则会在IE中产生一个沉闷的方框,但在Mozilla浏览器中,它会生成一个带圆角的纯粹的盒子,使它看起来非常专业。

完成工作,感谢Jim。