使用 jQuery 和 Ajax.BeginForm 将带有“正在加载...” spinner.gif 的 div 居中

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4461247/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 17:18:06  来源:igfitidea点击:

Centering a div with a "Loading..." spinner.gif using jQuery and Ajax.BeginForm

jquerycssasp.net-mvcajax

提问by awrigley

The Setup

设置

I have designed a very easy to use MVC wizard. The cherry on the cake is a spinner gif that will appear when I change wizard step. I want it to center on the page, regardless of the size of the browser window.

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

You can see an example of this at:

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

Sample Wizard

样品向导

PLEASE DON'T COMPLETE THE WIZARD, UNLESS YOU HAVE ENCEPHALITIS...

请不要完成向导,除非您患有脑炎...

The Problem

问题

Problem is, I have a centered CSS layout, controlled with the following rule:

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

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

And this rule seems to interact badly with the jquery code that centers the div with the spinner gif. Ie, it doesn't center.

并且这条规则似乎与将 div 与微调 gif 居中的 jquery 代码交互不良。即,它不居中。

The Code

编码

My MVC form code is:

我的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 code is:

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>

My Analysis

我的分析

As the jQuery code sets up the div panel to have an absolute position, it therefore has an absolute position relative to the first parent item that does not have position static (the default).

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

Therefore, as a result of the margin hack used to center the page, there is something creeping into the jQuery calculation that upsets the apple cart.

因此,作为用于使页面居中的边距黑客的结果,jQuery 计算中有些东西会扰乱苹果购物车。

Ie:

IE:

The jQuery calculation is based on the size of the window, but the position of the #PleaseWait panel is positioned with respect to the #PageContainer div (this div is part of the layout). Obviously, these are two very different things. I therefore thought I would get away with figuring out the constant values to subtract from the top and left calculations for the #PleaseWait div.

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

However, the results are unpredictable and I am now too befuddled to figure it out. Help!

然而,结果是不可预测的,我现在太糊涂了,无法弄清楚。帮助!

Any help much appreciated.

非常感谢任何帮助。

JOB DONE!:

任务完成!:

Problem sorted. See Jim's accepted answer for the ideas, my follow up answer for full the implementation.

问题排序。请参阅 Jim 对这些想法的接受答案,以及我对完整实施的后续回答。

采纳答案by awrigley

Hack 1:

黑客 1:

I have "solved" the problem in that I have moved the #PleaseWait div to the very top of the site's master view. That way, #PageContanier, with its relative position, is not interacting with the set up. It now works.

我已经“解决”了这个问题,因为我已经将#PleaseWait div 移到了站点主视图的最顶部。这样,#PageContanier 及其相对位置不会与设置交互。它现在可以工作了。

The downside is that now EVERY page in the app has this div (with style="display:none;"). Only some of them will ever need it.

缺点是现在应用程序中的每个页面都有这个 div(style="display:none;")。只有其中一些人会永远需要它。

Hack 2:

黑客 2:

An improvement on Hack 1 is to create a Content placeholder just under the body tag. That way, from the pages where you need it, you can inject whatever div you need to have a centered panel on your pages.

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

This eliminates the redundancy in pages that don't use the panels, and gives you a lot flexibility. However, the downside is that each time you have to write the code. Not exactly DRY, so...

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

Look Mum, no Hacks!:

看妈妈,没有黑客!:

Thanks to Jim's suggestion (see accepted answer), I have cracked the issue. No more hacks required.

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

I can use a pure jQuery solution, as follows (if javascript is disabled, nothing happens, which is good).

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

So:

所以:

I created a Utilities.js file and put in there the following function:

我创建了一个 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;
            }
            });

In my wizard.aspx view I put the following jQuery code:

在我的 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;
                }
            }

The isValid() function is used, as before, in my MVC AJAX form (see below).

和以前一样,在我的 MVC AJAX 表单中使用了 isValid() 函数(见下文)。

The MVC Ajax Form does not change. Ie:

MVC Ajax 表单没有改变。IE:

@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 *@
        }

If javascript is disabled, the solution still works. The spinner gif doesn't show which is the correct behaviour, as there is no asynch request, just a page refresh.

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

And with this little framework, the hack detailed above is no longer needed: only the pages that explicitly request it have the PleaseWait div.

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

To style the PleaseWait div, I have used:

为了设置 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>

This rule will produce a dull square box in IE, but in Mozilla browsers, it will produce a natty wee box with rounded corners, making it look very pro.

这条规则在 IE 中会产生一个暗淡的方形框,但在 Mozilla 浏览器中,它会产生一个带有圆角的整洁的小框,使它看起来非常专业。

Job done, thanks to Jim.

工作完成,感谢吉姆。

回答by jim tollan

aw,

啊,

don't know why this didn't occur to me sooner. You could overcome the entire issue of the additional div in your master template by using jquery. a la:

不知道为什么我没有早点想到这一点。您可以使用 jquery 克服主模板中附加 div 的整个问题。啦啦:

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();
}

it may or may not be appropriate, but would certainly limit it to only the pages that actively invoked the spinner....

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

回答by Jamie

Have you thought of using BlockUI, seems a good candidate for this. I used it on one of our projects before and it's very very good.

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