2013-10-20 26 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()如在上面的例子。
希望你會喜歡它。