1

我正在尝试计算具有隐藏父元素的元素的宽度。因为该元素不可见,所以它返回零宽度。所以我写了这个小函数:

/**
  * Compute the width of an element if it were to be visible.
  *
  * $element: The element you want to compute the width of
  * $hiddenParent: A parent (ancestor) of $element which is currently hidden
  *
  * Returns: the width of $element if it were to be visible.
  */
var getDisplayedWidth = function($element, $hiddenParent) {
    var oldDisplay = $hiddenParent.css("display");
    $hiddenParent.show();
    var displayedWidth = $element.width();
    $hiddenParent.css("display",oldDisplay);
    return displayedWidth;
};

它工作并返回显示的宽度。但问题是,“oldDisplay”的值并不是内联显示属性的真正旧值。它是显示属性的计算值。(这不是一个错误——这完全是我根据 jQuery 的文档所期望的。)

这种细微的差异意味着该方法在以下用例中失效 - 我们有一个元素,它最初display:none是通过类而不是内联样式控制的。所以oldDisplay设置为“无”。现在,当显示被放回时,display:none变成了内联样式。稍后在执行中,当其他一些 javascript 添加一个类以使其可见时,内联样式优先并且元素不会出现。

在这种情况下,我真正想做的是仅提取“显示”属性的内联样式版本。如果元素没有内联“显示”属性(如上例所示),那么我想oldDisplay将其设置为空字符串。

现在我已经解释了背景,简单地说就是这个问题 - 我如何仅从内联样式中获取 CSS 属性?

(PS:我知道我可以通过手动解析“style”属性来做到这一点。但我觉得必须有更好的方法,尤其是使用jQuery。)

4

3 回答 3

2

这样做的问题是,如果父元素设置为 display:none,那么所有子元素也将显示 display:none 作为其计算样式。因此,除非您知道所有父母都是可见的,否则在相关元素上设置 display visible 可能不起作用。

此外,您不希望通过覆盖其先前的内联显示模式或覆盖其样式表声明来影响您的元素样式。

我写了这个小宝石来解决这两个问题:

jQuery.fn.locate = function() {
var o = this, a = [],
    n = o.filter(':hidden').parents(':hidden').addBack()
        .each(function(i){ a[i] = $(this).get(0).style.display || '' })
        .css('display','block'),
    xy = o.offset(), p = [ xy.left - parseInt(o.css('margin-left'),10), o.width(), xy.top - parseInt(o.css('margin-top'),10), o.height() ]
    n.each(function(i){ $(this).get(0).style.display = a[i] })
    return {'left':p[0], 'right':p[0] + p[1], 'width':p[1], 'top':p[2], 'bottom':p[2] + p[3], 'height':p[3]}
}

这将搜索包括原始元素在内的所有父元素,记录它们的内联样式属性,将它们全部设置为 display:block,记录您的原始元素绝对定位信息,恢复所有受影响元素的内联样式,然后返回一个带有定位数据。您可以修改它以更改它返回的数据。

var t = $(elem).locate()
alert(t.width)

这是一个更复杂的版本,它允许您存储包含多个元素的 jQuery 对象的定位数据。它将信息存储到每个元素的 .data() 属性中,并返回原始对象以维护链接。

jQuery.fn.markLocation = function() {
var o = this, a = [],
    n = o.filter(':hidden').parents(':hidden').addBack()
        .each(function(i){ a[i] = $(this).get(0).style.display || '' })
        .css('display','block')
    o.each(function(){
        var t = $(this), xy = t.offset(),
            p = [ xy.left - parseInt(t.css('margin-left'),10), t.width(), xy.top - parseInt(t.css('margin-top'),10), t.height() ]
        t.data({'left':p[0], 'right':p[0] + p[1], 'width':p[1], 'top':p[2], 'bottom':p[2] + p[3], 'height':p[3]})
    })
    n.each(function(i){ $(this).get(0).style.display = a[i] })
    return o
}

要使用它:

var t = $('elems').markLocation()
var d = t.find(singleElement).data()
alert(d.width)

是的,我故意以一种异端混乱的方式编码,并且从不打算改变:)

享受

于 2013-05-21T06:34:35.770 回答
1

如果样式display: none在样式表中设置为,你不能像这样获得宽度:

function getElWidth(el, elParent){
  elParent.show() // inline display: block
  var w = el.width();
  elParent.attr('style', '');
  return w;
}

我想这使用了style属性,但只是一个想法。

于 2012-11-28T19:28:18.200 回答
0

一些代码可以在每个样式属性的 json 中获取单独的样式。

$(selector,this).each(function(index)
{
   var styletag=$(this).attr('style');
   var stylestemp=styletag.split(';');
   var styles={};
   var c='';
   for (var x in stylestemp) {
     c=stylestemp[x].split(':');
     styles[$.trim(c[0])]=$.trim(c[1]);
   }
   // do whatever with the styles json here.
});

或者也试试这个:

$(".someSelector[style*=inline]").attr("myAttribute");// 在方括号中给出任何带有条件的选择器,这将过滤掉具有内联样式的选择器。

于 2012-11-28T19:29:02.913 回答