【问题标题】:Using calc() for height of jQuery-ui dialog to set it based on window height使用 calc() 为 jQuery-ui 对话框的高度设置它基于窗口高度
【发布时间】:2018-05-22 16:36:31
【问题描述】:

我正在尝试使 jQueryUI 对话框成为 窗口 的高度和宽度(减去一些填充)。理想情况下,我会将这些选项设置为类似于calc(100% - 100px) 的 CSS 值,而不是抓取$(window).height(),然后在用户调整窗口大小时必须处理更新内容

这适用于width,但不适用于height

这是我的 HTML:

<button>Open Dialog</button>
<div id="filters-dialog" style="display: none;">
  asdf<br/>
  asdf<br/>
  asdf<br/>
  asdf<br/>
</div>

还有我的 jQuery:

$("button").on("click", function(){
  $("#filters-dialog").dialog().dialog("open");
})
$("#filters-dialog").dialog({
  autoOpen: false,
  modal: true,
  width: "calc(100% - 100px)",
  height: "calc(100% - 100px)",
});

我尝试过的一些事情包括设置minHeight 选项,将heightminHeight 设置为open:create: 上的对话框选项,尝试覆盖.ui-dialog 的CSS heightmin-heighttopopen:create: (以这种方式设置 CSS 似乎适用于某些属性但不适用于这些属性),将 body 和 html 的 CSS 设置为 height: 100%,然后抛出!important 左右。

这里是 a fiddle,我的尝试已被注释掉。提前感谢您的帮助。

【问题讨论】:

    标签: jquery css jquery-ui


    【解决方案1】:

    jQuery UI 的 Dialog 小部件只接受高度为 Number"auto",传递它 "calc(100% - 100px)" 将默认为 "auto"。它的 min/maxHeight 只是数字。对话框打开后,您必须以编程方式执行此操作。请记住,当您调用.dialog() 属性时,您选择的是对话框内的内容,而不是对话框的包装 div,因此要设置窗口的实际高度,您需要选择父级.dialog():

    $("button").on("click", function(){
      $("#filters-dialog").dialog().dialog("open");
    });
    
    $("#filters-dialog").dialog({
      autoOpen: false,
      modal: true,
      width: "calc(100% - 100px)",
      open: function() {
        $(this).parent().css("height", "calc(100% - 100px)");
      }
    });
    

    请记住,如果您这样做,内容部分将无法按原样正确调整大小,因此如果您的内容大于窗口,它会看起来很奇怪。

    【讨论】:

    • 感谢您的回答。不幸的是,在我的情况下,内容不可避免地会比窗口长。我想以编程方式处理该问题的一种方法是将内容框的高度设置为"calc(100% - " + adjustment + "px)",其中adjustment = 对话框标题栏高度+ 对话框按钮窗格高度(不在我的示例中)+ 对话框填充+ 对话框边框。 Blech,感觉很脏,但我认为它会起作用。
    • @MaxStarkenburg 发布了一个可能有帮助的答案。
    【解决方案2】:

    宽度和高度通过样式属性在小部件上设置。例如:

    <div style="position: absolute; height: auto; width: 404px; top: 50px; left: 45.8px; z-index: 101;" tabindex="-1" role="dialog" class="ui-dialog ui-widget ui-widget-content ui-front ui-draggable ui-resizable" aria-describedby="filters-dialog" aria-labelledby="ui-id-1">
    

    此处设置宽度,高度为auto。然后计算内容的高度,而不是整个对话框 div:

    <div id="filters-dialog" style="width: auto; min-height: 0px; max-height: none; height: 201.6px;" class="ui-dialog-content ui-widget-content">
    

    这一切都设置为包装的一部分,可以通过widget 选项访问。要调整这一点,您不能使用 CSS,因为元素上的样式属性将受到控制。 (可以尝试将"" 设置为值,但我认为它不会将其全部丢弃。)

    调整宽度应该非常直接。调整高度,没那么多。高度不仅仅是100% - 100px,它是(100% - 100px) - .ui-dialog-content padding - .ui-dialog-titlebar height (with padding) - .ui-dialog padding。不是不可能,只是复杂。

    在这一点上,就个人而言,我会使用窗口的高度和宽度并完成它。您预计用户多久调整一次窗口大小?

    那么如何前进。可以试试这样的:

    open: function() {
      $(this).dialog("widget").css("width", "calc(100% - 100px)");
      $(this).dialog("widget").find(".ui-dialog-content").css("height", "calc(100% - 100px)");
    }
    

    它并不漂亮,但它可以满足需要。工作:https://jsfiddle.net/Twisty/4cjm2ood/

    我不知道这会产生预期的结果。 100% 高度将绑定到父级,因此计算出错误的高度。最好去掉样式,让 CSS 完成工作。

    首先要记住的是,我们需要有选择地删除某些样式,而不是全部清除。

    工作示例:https://jsfiddle.net/Twisty/4cjm2ood/2/

    JavaScript

    $(function() {
      function removeStyleAttr(list, item) {
        var parts = list.split(";");
        parts = parts.slice(0, -1);
        var styles = {},
          newList = "";
        $.each(parts, function(i, s) {
          var k = s.split(":")[0].trim();
          var v = s.split(":")[1].trim();
          styles[k] = v;
        });
        if (typeof item != "string") {
          $.each(item, function(k, v) {
            delete styles[v];
          });
        } else {
          delete styles[item];
        }
        $.each(styles, function(key, val) {
          newList += key + ": " + val + "; "
        });
        return newList.slice(0, -1);
      }
    
      $("button").on("click", function() {
        $("#filters-dialog").dialog("open");
      });
    
      $("#filters-dialog").dialog({
        autoOpen: false,
        classes: {
          "ui-dialog": "ui-diag-top",
          "ui-dialog-content": "ui-diag-content"
        },
        modal: true,
        width: $(window).width() - 100,
        height: $(window).height() - 100,
        open: function() {
          var s1 = $(this).dialog("widget").attr("style");
          var s2 = removeStyleAttr(s1, ["width", "height"]);
          var s3 = $(this).dialog("widget").find(".ui-dialog-content").attr("style");
          var s4 = removeStyleAttr(s3, "height");
          $(this).dialog("widget").attr("style", s2);
          $(this).dialog("widget").find(".ui-dialog-content").attr("style", s4);
        }
      });
    });
    

    首先是一个小函数:removeStyleAttr(List, Item)

    • List (String) - 分配给一个元素的所有 CSS 样式的列表
    • Item (String, Array) - 我们要移除的特定样式
    • 返回值是所有剩余 CSS 样式的新字符串。

    所以现在我们有一种方法可以从元素中切出一个特定的样式,例如“宽度”。一旦这些被删除,我们就可以使用我们自己的 CSS。为此,我建议使用classes 添加您自己的类名。

    使用open 回调,我们剥离了包装器的widthheight,以及内容的height。这会将控件返回给我们的 CSS。

    CSS

    .ui-diag-top {
      width: calc(100% - 100px);
      height: calc(100% - 100px);
    }
    
    .ui-diag-content {
      height: auto;
    }
    

    包装器大小合适,工具栏保持不变,内容将是auto 以填充其余部分。

    现在,如果您认为必须经常这样做,您可以考虑使用 Widget Factory 并构建一个超级对话框,允许您接受 String 值而不是 Integer 作为宽度和高度。

    更新 1

    width 选项将毫无问题地接受 calc(100% - 100px)height 被操作并需要一些覆盖。

    更新 2

    虽然 widthheight 存储为值 calc(100% - 100px),但有一些调整大小函数可以与这些值进行比较:

    https://github.com/jquery/jquery-ui/blob/master/ui/widgets/dialog.js

    第 788 行:if ( options.minWidth &gt; options.width ) {

    第 789 行: options.width = options.minWidth;

    第 790 行:}

    即使你认为你可以,你也冒着破坏某些东西的风险。我只想创建一个可以在调整widthheight 的调整大小事件期间调用的函数。

    更新 3

    这是一个更简洁的解决方案,它允许调整大小并且不依赖 CSS。

    工作示例:https://jsfiddle.net/Twisty/4cjm2ood/6/

    JavaScript

    $(function() {
      $.widget("custom.superDialog", $.ui.dialog, {
        options: {
          useWindowOffset: false,
          windowOffset: 0
        },
        open: function(event, ui) {
          if (this.options.useWindowOffset) {
            this.applyWindowOffset();
          }
          this._super(event);
        },
        _resetWidth: function(ow, dw) {
          var nw = $(ow).width() - dw;
          this._setOption("width", nw);
        },
        _resetHeight: function(ow, dh) {
          var nh = $(ow).height() - dh;
          this._setOption("height", nh);
        },
        applyWindowOffset: function() {
          var o = this.options.windowOffset;
          if (typeof o == "object" && o.length > 1) {
            this._resetWidth(this.window, o[0]);
            this._resetHeight(this.window, o[1]);
          }
          if (typeof o == "number") {
            this._resetWidth(this.window, o);
            this._resetHeight(this.window, o);
          }
          console.log(this.options);
        },
        resizeWindowOffset: function(event) {
          this.applyWindowOffset();
          this._size();
        }
      });
    
      $("button").on("click", function() {
        $("#filters-dialog").superDialog("open");
      });
    
      $("#filters-dialog").superDialog({
        autoOpen: false,
        modal: true,
        title: "I am offset!",
        useWindowOffset: true,
        windowOffset: 100
      });
    
      $(window).resize(function(e) {
        $("#filters-dialog").superDialog("resizeWindowOffset", e);
      })
    });
    

    利用小部件工厂,我们可以创建自己的自定义对话框小部件。我们添加了一些选项和方法,以便我们可以使用基于窗口偏移量的大小。

    • useWindowOffset:布尔型,默认false
    • windowOffset:整数或数组,默认0。将 useWindowOffset 设置为 true 并设置以像素为单位的偏移值或以像素为单位的数组 ([width, height])。
    • applyWindowOffset():这里不接受任何争论。将新的宽度和高度值应用于对话框。在open之前执行。
    • resizeWindowOffset():接受event,但此时不使用它。在调整窗口大小以应用大小更改时调用。

    没有更多关于此的更新。希望对您有所帮助。

    【讨论】:

    • 哇,感谢您的许多选择和解释。我觉得很糟糕,你通常提供了这么多我可能无法使用的工作。也许我应该在问题中指定不要太复杂。 :-) 期待可能有一个我错过的相当轻松的解决方案,可以轻松地将 calc() 用于高度。但我从你的代码中学到了很多东西。
    • “您预计用户多久调整一次窗口大小?” 无论好坏,在测试我的工作响应能力时,重要的利益相关者很可能会调整他们的窗口. “我只是创建一个可以在调整宽度和高度的调整事件期间调用的函数。” 这就是我现在所做的。它比我预期的要轻松。但是当我没有预料到的情况下失败时,我无疑会回到你的代码。再次感谢您!
    猜你喜欢
    • 2015-01-15
    • 2012-01-27
    • 1970-01-01
    • 2015-02-26
    • 2017-05-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-28
    相关资源
    最近更新 更多