弄清楚子元素是否在父元素之外

时间:2015-11-27 09:18:27

标签: jquery css

我想弄清楚子元素在父元素中是否可见。通过这样做,我测试父母的width是否大于或小于孩子position().left

由于我有许多单独的父元素和子元素,因此我运行each个函数。

//Each p in instagram feed
jQuery('#instagram-feed .meta-data p').each(function(){

    // Get width of this p element
    var parentWidth = jQuery(this).width();

    // Each a element within this p
    jQuery(this).children('a').each(function(){

        // Compare p element width of with position of this a
        if(parentWidth < jQuery(this).position().left) {

            // If position is larger then width
            jQuery(this).css('color', 'green');
            console.log("Not inside element");

        } else {

            // If position is smaller then width
            jQuery(this).css('color', 'red');
            console.log("Inside element");
        }

        console.log(jQuery(this).position().left);

    });

});

我做了一个小提琴,你可以看到并测试:http://jsfiddle.net/fprm7mgd/9/(确保三个元素是水平的,以便看到&#34; bug&#34;)

enter image description here

问题在于,在第三个父元素中,似乎position().left从第一个父元素或父元素上方计数。为什么第三个父级中的链接变为绿色?因为它在父母的内部,所以应该是红色的...我做错了什么?

4 个答案:

答案 0 :(得分:2)

您可以使用jQuery(this).position().left - parent.position().left来计算a元素的左侧,如下所示:

//Each p in instagram feed
jQuery('#instagram-feed .meta-data p').each(function(){

    // Get width of this p element
    var parentWidth = jQuery(this).width();
    var parent = jQuery(this);

    // Each a element within this p
    jQuery(this).children('a').each(function(){

        var elementLeft = jQuery(this).position().left - parent.position().left;
        // Compare p element width of with position of this a
        if(parentWidth < elementLeft) {

            // If position os larger then width
            jQuery(this).css('color', 'green');
            console.log("Not inside element");

        } else {

            // If position os smaller then width
            jQuery(this).css('color', 'red');
            console.log("Inside element");
        }

        // ...

    });

});

看到这个工作小提琴:http://jsfiddle.net/fprm7mgd/29/

答案 1 :(得分:1)

如果您阅读jQuery.position的文档,您会发现该位置相对于offset parent。示例中的偏移父项是<html>元素,所有左侧值都与该元素相关。

解决方案是为CSS添加一个小调整:制作段落元素position: relative

&#13;
&#13;
jQuery(window).on("load resize", function() {
  jQuery("#instagram-feed .meta-data p").each(function() {
    var parentWidth = jQuery(this).width();
    console.log("parent", this, "width", parentWidth);
    jQuery(this).children("a").each(function() {
      var childLeft = jQuery(this).position().left;
      console.log("child", this, "left", childLeft, "offset parent", this.offsetParent);
      if (parentWidth < childLeft) {
        jQuery(this).css("color", "green");
      } else {
        jQuery(this).css("color", "red");
      }
    });
  });
});
&#13;
.meta-data {
  float: left;
  margin-right: 50px;
}
p {
  width: 160px;
  padding: 5px;
  white-space: nowrap;
  background: silver;
  display: inline-block;
  /* added */
  position: relative;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

<div id="instagram-feed">
  <div class="meta-data">
    <p>fgdfgfdg fdgf df df <a href="#">link</a></p>
  </div>
  <div class="meta-data">
    <p>fgdfgfdg fdgf df df dsfsdf <a href="#">link</a></p>
  </div>
  <div class="meta-data">
    <p>fgdfgfdg fdgf <a href="#">link</a></p>
  </div>
</div>
&#13;
&#13;
&#13;

答案 2 :(得分:1)

  1. 您应该使用offset而不是position来更安全。那是因为根据http://api.jquery.com/offset/
  2.   

    .offset()方法允许我们检索一个的当前位置   元素相对于文档。将此与.position()对比,   它检索相对于偏移父项的当前位置

    1. offsetposition会返回包含lefttop属性的对象。您真正需要比较的是left锚点与父级right。因此,只需将父{的width添加到其offset().left即可。现在将其与主播的left进行比较。
    2. 像这样:

      $('#instagram-feed .meta-data').each(function(){
          var parentRight = $(this).offset().left + $(this).width();
          $(this).find('a').each(function(){
              var self = $(this);
              if(self.offset().left > parentRight) {
                  self.css('color', 'green');
              } else {
                  self.css('color', 'red');
              }
          });
      });
      

      演示小提琴:http://jsfiddle.net/abhitalks/fprm7mgd/33/

      演示代码段

      $('#instagram-feed .meta-data').each(function(){
          var parentRight = $(this).offset().left + $(this).width();
          $(this).find('a').each(function(){
      		var self = $(this);
              if(self.offset().left > parentRight) {
                  self.css('color', 'green');
              } else {
                  self.css('color', 'red');
              }
          });
      });
      .meta-data {
          float: left;
          margin-right: 50px;
          border: 1px solid #ddd;
      }
      
      p {
          width: 160px;
          padding: 5px;
          white-space: nowrap;
          background: silver;
          display: inline-block;
      }
      <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
      <div id="instagram-feed">
          <div class="meta-data">
              <p>
                  fgdfgfdg fdgf df df <a href="#">link</a>
              </p>
          </div>
          <div class="meta-data">
              <p>
                  fgdfgfdg fdgf df df dsfsdf <a href="#">link</a>
              </p>
          </div>
          <div class="meta-data">
              <p>
                  fgdfgfdg fdgf <a href="#">link</a>
              </p>
          </div>
      </div>

      更好的解决方案是使用Javascript getBoundingClientRect方法,该方法返回元素的大小及其相对于视口的位置。

      var parents = document.querySelectorAll('.meta-data');
      [].forEach.call(parents, function(elem) {
          var parentBounds = elem.getBoundingClientRect(), 
              anchor = elem.getElementsByTagName('A')[0], 
              anchorBounds = anchor.getBoundingClientRect()
          ;
          if (anchorBounds.left > parentBounds.right) {
              anchor.classList.add('red');
          } else {
              anchor.classList.add('green');
          }
      });
      

      演示小提琴2:http://jsfiddle.net/abhitalks/n0ak4y7w/

      Demo Snippet 2:

      var parents = document.querySelectorAll('.meta-data');
      
      [].forEach.call(parents, function(elem) {
          var parentBounds = elem.getBoundingClientRect(), 
              anchor = elem.getElementsByTagName('A')[0], 
              anchorBounds = anchor.getBoundingClientRect()
          ;
          if (anchorBounds.left > parentBounds.right) {
              anchor.classList.add('green');
          } else {
              anchor.classList.add('red');
          }
      });
      .meta-data {
          float: left;
          margin-right: 50px;
          border: 1px solid #ddd;
      }
      
      p {
          width: 160px;
          padding: 5px;
          white-space: nowrap;
          background: silver;
          display: inline-block;
      }
      
      .red { color: #f00; }
      .green { color: #3c3; }
      <div id="instagram-feed">
          <div class="meta-data">
              <p>
                  fgdfgfdg fdgf df df <a href="#">link</a>
              </p>
          </div>
          <div class="meta-data">
              <p>
                  fgdfgfdg fdgf df df dsfsdf <a href="#">link</a>
              </p>
          </div>
          <div class="meta-data">
              <p>
                  fgdfgfdg fdgf <a href="#">link</a>
              </p>
          </div>
      </div>

答案 3 :(得分:0)

最终解决方案:

//This will only work properly if margin-left and margin-right is equal. Same for padding.
function removefromTabindex(myElement, ellipsisSize){

    var ellipsisSizeInit = ellipsisSize;
    if (ellipsisSizeInit === undefined || ellipsisSizeInit === null) {
        ellipsisSizeInit = 0;
    }

    jQuery(myElement).each(function(){
        var myMargin = (jQuery(this).outerWidth(true) - jQuery(this).width()) / 2;
        myMargin = myMargin + ellipsisSizeInit;
        var parentRight = (jQuery(this).position().left + jQuery(this).outerWidth(true)) - myMargin;

        jQuery(this).find('a').each(function(){
            if((jQuery(this).position().left) > parentRight) {
                jQuery(this).attr('tabindex', '-1');
            } else {
                if ( jQuery(this).attr('tabindex') === '-1') {
                    jQuery(this).removeAttr('tabindex')
                }
            }
        });

    });

};

//Run function
jQuery(document).ready(function(){
    removefromTabindex('#instagram-feed .meta-data p');
});

//For a responsive view
jQuery(window).resize(function () {
    removefromTabindex('#instagram-feed .meta-data p');
});

这包括填充和边距,但只有当左边和右边的边距和填充相等时才能正常工作,因为我没有找到任何完美的方法来获取边距和填充作为int像素(如果边距由百分比或ems设置)。我必须通过元素的内部和外部宽度来计算边距和填充。

它在开始时加载,但也在调整大小时加载,以确保它在响应式设计中重新计算值。现在也可以通过参数向函数添加更多元素。还添加了省略号宽度作为参数,以便您可以将该宽度添加到计算中。

通过使用此脚本,您可以使用CSS缩短文本并从tab-index中删除溢出的链接,这可能是一件好事。

http://jsfiddle.net/fprm7mgd/46/