width() 和 height() 适用于没有 jQuery 的现代浏览器

2024-01-29

我正在尝试为弹性 div 实现一个简单的折叠/展开效果,即当元素的实际尺寸未通过 CSS 设置时,因此无法简单确定。所以我需要 jQuery 的 width() 和 height() 的等效项来表示任意元素;这些方法应该返回可分配给 *.style.width/height 的内容以实现折叠/展开效果。这些方法也可以是设置器,尽管不一定,因为它无论如何都是微不足道的(或者不是吗?)

兼容性:IE8+ 和 3 种浏览器:Firefox、Chrome、Safari。所以。除了我目前不想做的“使用 jQuery”之外,没有其他答案。问题是我不需要支持像 IE6/7 和 Netscape 这样的老式浏览器。我希望我的代码对于现代浏览器来说是简单的、原生的 JavaScript。放弃 IE8 转而使用 IE9 也是一种选择。

我认为这个答案可能对许多网络开发人员有用。谢谢!

编辑:我当然理解,分析 jQuery(并放弃过时的怪癖)是一个不错的选择,但我认为有人已经做到了这一点并且可以与我们分享。


这是我今天在使用 IE8、FF、Chrome 和 Safari 之后想到的问题的答案。

假设我们想要使用尽可能少的 JavaScript 且没有 jQuery 来垂直折叠和展开一个 div 元素(因此,为了简单起见,我们只讨论高度)。可能是您希望在页面上很好地显示和隐藏的内联错误消息框。消息框本身是有弹性的,你不知道它的实际尺寸。这里有两个一般性问题需要解决:

问题#1:offsetHeight、clientHeight 和scrollHeight 属性在不同浏览器中不一致是众所周知的。你不能依赖它们,特别是当 margin/padding/border 设置为 0 以外的值以及 CSS 高度不是默认值时(即实际折叠/展开元素时)。有 getComputedStyle(),但它仅在正常浏览器上可用,而在 IE 中不可用。 OTOH,IE 的 currentStyle 属性不会返回您可能期望的计算值(例如,您可能会看到“auto”作为高度值)。事实证明,没有边距/填充/边框的 offsetHeight 在所有现代浏览器上都是可靠且兼容的。

问题#2:(据我所知)对 div 元素进行动画处理的唯一方法是更改​​ style.height,但是,它不包括填充和边框,因此您无法将框动画化为 0 或对于具有非零填充和边框的元素,从 0 开始动画。 (最重要的是,IE 不接受 0px 作为 style.height,所以最小尺寸无论如何都是 1px)。

解决这两个问题的方法是用另一个具有默认样式的 div 包裹您的盒子,即 padding/margin/border 全部设置为 0,这是新 div 的默认样式。您想要折叠和展开的盒子应该位于内部,并且不应该有边距设置,如果需要,只能有填充和边框。这样,您将能够 (1) 通过 offsetHeight 可靠地确定弹性内盒的高度,以及 (2) 以 1 像素为单位设置外盒高度的动画。

那么,假设我们想要为其设置动画:

<div id="errmsg" style="display:none">
    <div class="errmsg">
        <div class="window-close" onClick="javascript:showErrMsg('', this.parentNode.parentNode)"></div>
        <div id="errmsg.text"></div>
    </div>
</div>

盒子一开始是看不见的。 “window-close”类是右侧有一个十字的小框,用于在单击时隐藏该框。使用空字符串调用 showErrMsg() 会折叠消息框(见下文)。

用于为该错误消息框设置动画的 JavaScript 代码如下(我还对不透明度进行动画处理,为简单起见,此处省略了该动画):

var ANIMATE_STEPS = 10;
var ANIMATE_DELAY = 20;


function _obj(obj, parent)
{
    if (typeof obj == 'string')
        obj = (parent ? parent : document).getElementById(obj);
    return obj;
}

function _setStyleHeight(obj, h)
{
    _obj(obj).style.height = Math.round(h) + 'px';
}

function _animateVertFold(obj, cur, by, lim)
{
    obj = _obj(obj);
    cur += by;
    if (by < 0 && cur <= 1)
    {
        obj.style.display = 'none';
        _setStyleHeight(obj, 1); // IE doesn't accept 0
    }
    else if (by > 0 && cur >= lim)
    {
        _setStyleHeight(obj, lim);
    }
    else
    {
        _setStyleHeight(obj, cur);
        setTimeout('_animateVertFold(\'' + obj.id + '\', ' +
            cur + ', ' + by + ', ' + lim + ')', ANIMATE_DELAY);
    }
}

function _expandElem(obj)
{
    obj = _obj(obj);
    if (obj.style.display == 'none')
    {
        obj.style.overflow = 'hidden';
        _setStyleHeight(obj, 1);
        obj.style.display = 'block';
        var innerDiv = obj.getElementsByTagName('div')[0]; // better way?
        var h = innerDiv.offsetHeight;
        if (h > 0)
            _animateVertFold(obj, obj.offsetHeight, h /  ANIMATE_STEPS, h);
    }
}

function _shrinkElem(obj)
{
    obj = _obj(obj);
    if (!obj.style.display || obj.style.display != 'none')
    {
        obj.style.display = 'block';
        obj.style.overflow = 'hidden';
        var h = obj.offsetHeight;
        _animateVertFold(obj, h, - h /  ANIMATE_STEPS, h);
    }
}


function showErrMsg(msg, id)
{
    id || (id = '_errmsg');
    obj = _obj(id);
    if (msg != '')
    {
        _obj(id + '.text').innerHTML = msg;
        _expandElem(obj);
    }
    else
        _shrinkElem(obj);
}

您可以调用 showErrMsg(),代码将处理其余的事情。您必须将窗口关闭类定义为模仿 GUI 关闭窗口按钮的类。当然,“errmsg”类作为一个具有不同背景颜色、边框和可能字体的盒子。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

width() 和 height() 适用于没有 jQuery 的现代浏览器 的相关文章

随机推荐