2013-10-20 32 views
8

更新我想避免通过所有元素的父母,依次测试每个元素,但这是我的最佳解决方案设法找到迄今为止,如在this answer检测一个元素是否有位置:通过jQuery修复(可能通过父元素)


内的事件处理程序,我想检测目标元素的位置是否相对于视口(固定)或文档(静态,相对或绝对)。

鉴于一个元素的位置可能是固定的,因为它具有“position:fixed”,或者因为它的父母之一是“position:fixed”,检测元素的固定位置有效的方法是什么?

例如:

CSS

#one {position:relative; height:10px; width:10px} 

#two-wrapper {position:fixed; bottom:0; height:10px; width:10px} 
#two {height:10px; width:10px} 

HTML

<div id="one" class="trigger-event">element one</div> 

<div id="two-wrapper"> 
    <div id="two" class="trigger-event">element two</div> 
</div> 

JS

$(document).ready(function(){ 
    $('.trigger-event').on('mouseenter', function(event){ 
     var isFixed = .... ???? 

     if (isFixed) { 
      $(event.target).css('background','red'); 
     } else { 
      $(event.target).css('background','green'); 
     } 
    }); 
}); 

回答

11

这是一个解决方案,基于遍历元素的父项,依次检查每个元素的CSS位置值。

这是最有效的方式,还是有办法通过检查元素本身来检测有效定位?

http://jsfiddle.net/Q4mSJ/

CSS

.trigger-event {background:#ccc} 

#one {position:relative; height:50px; width:50px} 

#two-wrapper {position:fixed; bottom:0; height:50px; width:50px} 
#two {height:50px; width:50px} 

HTML

<div id="one" class="trigger-event">element one</div> 

<div id="two-wrapper"> 
    <div id="two" class="trigger-event">element two</div> 
</div> 

JS

function elementOrParentIsFixed(element) { 
    var $element = $(element); 
    var $checkElements = $element.add($element.parents()); 
    var isFixed = false; 
    $checkElements.each(function(){ 
     if ($(this).css("position") === "fixed") { 
      isFixed = true; 
      return false; 
     } 
    }); 
    return isFixed; 
} 

$(document).ready(function(){ 
    $('.trigger-event').on('mouseenter', function(event){ 
     var isFixed = elementOrParentIsFixed(event.target); 

     if (isFixed) { 
      $(event.target).css('background','red'); 
     } else { 
      $(event.target).css('background','green'); 
     } 
    }); 
}); 
+0

完美! :D +100 –

+0

很晚,恭喜,但+1 :-),因为我看到你的函数'elementOrParentIsFixed()'几乎和我下面一样,只是我的是一个jQuery插件而不是函数。 – ddlab

-1
$(document).ready(function(){ 
    $('.trigger-element').on('mouseenter', function(event){ 
     var position= $(this).css("position"); 

     if (position=="fixed") { 
      $(event.target).css('background','red'); 
     } else { 
      $(event.target).css('background','green'); 
     } 
    }); 
}); 

jsFiddle

+0

对不起,这只有在“position:fixed”直接设置在目标元素上时才起作用。当一个元素是静态的但它的父元素是固定的时它不起作用。 – pppggg

+0

@pppggg你可以阅读:http://api.jquery.com/parents/ –

+0

谢谢,我想这是“通过元素的父母走回来”的方法之一。 .parents()可以采用选择器参数。是否有一个选择器可以用来过滤父母的位置:固定? – pppggg

5

使用$(selector).offsetParent()您可以通过搜索祖先的选择器而不必加载所有父元素。它仍然需要遍历父元素,但一旦找到与所选位置最接近的元素(相对,绝对或固定),它就会停止。

http://jsfiddle.net/89y1buz9/11/

CSS:

div { 
border: 1px solid #ccc; 
} 
#outer { 
    height: 200px; 
    width: 120px; 
    position: fixed; 
    padding-top: 20px; 
} 
#inner { 
     width: 95px; 
    height: 150px; 
    margin: 0px auto; 
    position: relative; 
} 
#clickme { 
    width: 70px; 
    height: 50px; 
    cursor: pointer; 
    text-align: center; 
    line-height: 40px; 
    margin: 20px auto; 
} 

HTML:

<div id="outer"> 
    <div id="inner"> 
     <div id="clickme">ClickMe</div> 
    </div> 
</div> 

的Javascript:

function isFixed(ele, posType) { 
    var eleCheck = ele.offsetParent(), 
     returnVal; 
    posType = posType || "fixed"; 
    if (eleCheck.prop("tagName") === 'HTML') { 
     return false; 
    } 
    returnVal = (eleCheck.css("position") !== posType) ? isFixed(eleCheck): posType; 
    return returnVal; 
} 

用法: 带或不带第二个参数则默认调用它来寻找一个固定的元素

$(function() { 
    $("#clickme").on("click", function() { 
     if (isFixed($(this), "fixed") === "fixed") { 
      $(this).css("background", "red"); 
     } else { 
      $(this).css("background", "green"); 
     } 
    }); 
}); 
0

修订,见下文......

我下降了这里同时为此搜索纯JavaScript解决方案...但我希望有人会喜欢我的jQuery版本。

以下是两个功能,它们的工作方式略有不同,但性能差异很小。我没有测量它,但根据jsperf "each vs filter"的这个测试,.each()版本稍快。

尽管如此,我喜欢.filter()版本,因为它非常简短明了。

$.fn.isfixed = function(){ 
    var el = $(this); 
    var all = el.add(el.parents()); 
    return all.filter(function(){ 
     return $(this).css("position") === "fixed"; 
    }).length > 0; 
}; 

$.fn.isfixed = function(){ 
    var el = $(this); 
    var all = el.add(el.parents()); 
    var ret = false; 
    all.each(function(){ 
     if ($(this).css("position") === "fixed") { 
      ret = true; 
      return false; 
     } 
    }); 
    return ret; 
}; 

用法$('path > to > your > element').isfixed()并返回truefalse

UPDATE

而这里的纯JavaScript版本。原来,检测到el.style.position(固定/绝对/相对)不起作用,不知道为什么,但window.getComputedStyle(el)...呢。

var isfixed = function(elm) { 
    var el; 
    if (typeof elm === 'object') el = elm[0] || elm; 
    else if (typeof elm === 'string') el = document.querySelector(elm); 
    while (typeof el === 'object' && el.nodeName.toLowerCase() !== 'body') { 
     if (window.getComputedStyle(el).getPropertyValue('position').toLowerCase() === 'fixed') return true; 
     el = el.parentElement; 
    } 
    return false; 
}; 

它接受3种元件参数:
作为javascript对象:
var obj = document.querySelector('div#myID > span');

var obj = document.getElementById('span#someID');

作为jquery对象:
var obj = $('div#myID > span');

或作为选择只:
var obj = 'div#myID > span';

用法是简单地isfixed(obj);并提供布尔truefalse

而这里的最后的混合液(纯javascript作为jquery插件)

$.fn.isfixed = function(){ 
    var el = this[0]; 
    while (typeof el === 'object' && el.nodeName.toLowerCase() !== 'body') { 
     if (window.getComputedStyle(el).getPropertyValue('position').toLowerCase() === 'fixed') return true; 
     el = el.parentElement; 
    } 
    return false; 
}; 

用途:$('div#myID > span').isfixed()如在上面的例子。
希望你会喜欢它。