簡體   English   中英

使用JavaScript確定元素是否具有固定寬度或百分比寬度

[英]Determine whether element has fixed or percentage width using JavaScript

使用Mootools Element.Dimensions我可以獲得任何元素的計算大小(以像素為單位)。 但是,我無法確定元素是否已使用像素值或百分比值進行大小調整(除了具有內聯樣式的特殊情況)。

這樣做有明智的方法嗎? 我能想到的唯一解決方案(這是如此丑陋,幾乎不值得這個名字)是遍歷文檔樣式表,尋找與目標元素匹配的選擇器,然后查看目標屬性的聲明樣式。

背景

我試圖用CKEditor實例替換某個類的所有textareas。 理想情況下,100%寬度的textareas將被類似樣式的編輯器實例替換 - 因此它們可以在窗口調整大小上進行縮放 - 而固定大小的textareas將由固定大小的編輯器替換。

是的,我可以給他們一個不同的類(如果沒有好的解決方案,我將會這樣做),但理想情況下我希望能夠放入我的CKEditor腳本,並且無需調整HTML即可完成所有工作。

可以辦到。 看看這個問題( 為什么getComputedStyle在元素創建后立即返回'auto'作為像素值? )給出了提示。

如果將元素的樣式設置為display = none,然后調用getComputedStyle,您將獲得計算值(百分比寬度或'auto'或樣式表應用於元素的任何內容)而不是像素寬度。

工作代碼jsfiddle https://jsfiddle.net/wtxayrnm/1/

function getComputedCSSValue(ele, prop) {
  var resolvedVal = window.getComputedStyle(ele)[prop];
  //does this return a pixel based value?
  if (/px/.test(resolvedVal)) {
    var origDisplay = ele.style.display;
    ele.style.display = 'none';
    var computedVal = window.getComputedStyle(ele)[prop];
    //restore original display
    ele.style.display = origDisplay;
    return computedVal;
  } else {
    return resolvedVal;
  }
}

應該注意的是,這將導致布局重新呈現,但是,根據您的情況,它可能比遍歷所有樣式表規則或克隆元素(這可能導致某些級聯規則不應用)更簡單。

不熟悉Motools,但在jQuery中你可以做到。

點擊此處查看現場演示http://jsbin.com/ewuqa

或者檢查一下,它還處理多個匹配的CSS規則,但只返回正確的值(我唯一沒有理解的是if !important設置)。

包括JS

http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js
http://github.com/hafriedlander/jquery.concrete/raw/master/vendor/jquery.selector/jquery.class.js
http://github.com/hafriedlander/jquery.concrete/raw/master/vendor/jquery.selector/jquery.selector.js
http://github.com/hafriedlander/jquery.concrete/raw/master/vendor/jquery.selector/jquery.selector.specifity.js

自己的功能

function compare(as,bs) {
    return (as[0] - bs[0]) || (as[1] - bs[1]) || (as[2] - bs[2]);
}

//selector should only match a single element
//property is a css style-name
//returns the set css value (if set) for matched element, not the computed value
//also handles multiple matching rules and only returns most specific match
//doesn't handle !important
function whatIsSet(selector, property) {
    var se = $(selector);
    var regex = new RegExp("(.*)-(.)(.*)","g");
    var p = property;
    if (/-/.test(p)) {
        p = regex.exec(property);
        p = p[1] + p[2].toUpperCase() + p[3];
    }
    if (se.get(0).style[p] != undefined && se.get(0).style[p] != '')
        return se.get(0).style[p]; 

    var matchers = new Object();
    var mostSpecific = undefined;
    for(var i = 0; i < document.styleSheets.length; i++) {
        //IE support
        var rules =
            document.styleSheets[i].cssRules ?
              document.styleSheets[i].cssRules :
              document.styleSheets[i].rules;
        for (var j=0; j < rules.length; j++)
            if (rules[j].style[p])
                if (jQuery.inArray(se, $(rules[j].selectorText)))
                    matchers[rules[j].selectorText] = rules[j].style[p];
    }
    for(var i in matchers) {
        if(mostSpecific != undefined) {
            var ms = $.selector(mostSpecific).specifity();
            var is = $.selector(i).specifity();
            mostSpecific = compare(ms, is) > 0  ? mostSpecific : i;
        } else
            mostSpecific = i;
    }
    return matchers[mostSpecific];
}

CSS

body { background-color: #000; font: 16px Helvetica, Arial; color: #fff; }
#myElement {background-color: yellow; width:10%}
div {background-color: green; width:200px}
div#myElement  {background-color: blue; width:30%}
div.asd#myElement  {background-color: red; width:50%;}

HTML

  <div id="myElement" class="asd" style="width:91%">asd</div>
  <input
      type="button"
      onclick="javascript:alert('width originally set to: '+
          whatIsSet('#myElement', 'width'));"
      value="Tell me original width!"><br>
  <input
      type="button"
      onclick="javascript:alert('height originally set to: '+
          whatIsSet('#myElement', 'height'));"
      value="Tell me original height!"><br>
  <input
      type="button"
      onclick="javascript:alert('background-color originally set to: '+
          whatIsSet('#myElement', 'background-color'));"
      value="Tell me original background-color!"><br> 

我已經從一個封閉的副本中遷移並更新了我的答案:

如何判斷元素是否具有流體寬度

不想走下掃描風格的路線我發現這有效...但不幸的是只有firefox :(對我而言,如果元素沒有任何東西可以計算它的寬度(即它不是它應該返回它的原始值 - 這就是FireFox的作用:

function isElementFluid(elm){
  var clone = elm.cloneNode(false);
  if( window.getComputedStyle ) {
    value = window.getComputedStyle(clone,null).width;
  } else if( clone.currentStyle ) {
    value = clone.currentStyle.width;
  }
  return (value && String(value).indexOf('%') != -1 );
}

(尚未測試IE)

然而,Webkit和Opera返回一個空白值 - 這又是我同意FireFox實現的另一個例子,並且對其他人不屑一顧。

更新2

好吧,不是被計算機擊敗的粉絲;)所以提出了這個功能 - 完全超過頂部,但它似乎確實有效。 我還沒有在IE上測試這個,因為我現在還沒有Windows機器。 當原始的FireFox版本非常簡潔時,它很煩人,但這里的邏輯是合理的 - 它會回落到正常人類在測試某些東西是否有彈性時所做的事情。

function isElementFluid(elm){
  var wrapper, clone = elm.cloneNode(false), ow, p1, p2;
  if( window.getComputedStyle ) {
    value = window.getComputedStyle(clone,null).width;
  } else if( clone.currentStyle ) {
    value = clone.currentStyle.width;
  }
  /// the browsers that fail to work as Firefox does
  /// return an empty width value, so here we fall back.
  if ( !value ) {
    /// remove styles that can get in the way
    clone.style.margin = '0';
    clone.style.padding = '0';
    clone.style.maxWidth = 'none';
    clone.style.minWidth = 'none';
    /// create a wrapper that we can control, my reason for
    /// using an unknown element is that it stands less chance
    /// of being affected by stylesheets - this could be improved
    /// to avoid possible erroneous results by overriding more css
    /// attributes with inline styles.
    wrapper = document.createElement('wrapper');
    wrapper.style.display = 'block';
    wrapper.style.width = '500px';
    wrapper.style.padding = '0';
    wrapper.style.margin = '0';
    wrapper.appendChild(clone);
    /// insert the element in the same location as our target
    elm.parentNode.insertBefore(wrapper,elm);
    /// store the clone's calculated width
    ow = clone.offsetWidth;
    /// change the wrapper size once more
    wrapper.style.width = '600px';
    /// if the new width is the same as before, most likely a fixed width
    if( clone.offsetWidth == ow ){
      /// tidy up
      elm.parentNode.removeChild(wrapper);
      return false;
    }
    /// otherwise, calculate the percentages each time - if they
    /// match then it's likely this is a fluid element
    else {
      p1 = Math.floor(100/500*ow);
      p2 = Math.floor(100/600*clone.offsetWidth);
      /// tidy up
      elm.parentNode.removeChild(wrapper);
      return (p1 == p2) ? Math.round(p1)+'%' : false;
    }
  }
  else {
    p1 = (value && String(value).indexOf('%') != -1);
    return p1 ? value : false;
  }
}

在IE中, element.currentStyle.width 在許多其他瀏覽器中, getComputedStyle(element, null).getPropertyValue('width')

我懷疑它可以做到。 您非常准確地描述了原因:只有在元素的樣式屬性中才能訪問此類信息。 我能想到的唯一方法是稍微擴大父容器,看看textarea的大小是否成比例增長,但這可能並不總是可行的,並且可能很難使跨瀏覽器功能化。

不過,我對更積極的答案非常感興趣。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM