我需要倾听元素的相对位置。这对于动态布局问题特别有用。没有选项可以监听偶数position()或offset()属性的CSS样式。
为什么: 如果兄弟姐妹在对话框或表单中更改其维度(重新布局),则相对位置可能会发生变化。因此,对于交互式表单,这可以帮助使用,即父级的最大可用高度或宽度或类似的东西。
答案 0 :(得分:10)
此自定义jquery扩展通过计时器轮询侦听对象位置。 I.m.o.没有计时器就没有办法解决这个问题,因为在没有调用jquery的情况下可以改变位置(即重新布局同级元素)。此解决方案监视元素.position()和.offset()值。可以很容易地改进它来观看.css()样式或jQuery事件未涵盖的其他内容。
jQuery扩展程序:
jQuery.fn.onPositionChanged = function (trigger, millis) {
if (millis == null) millis = 100;
var o = $(this[0]); // our jquery object
if (o.length < 1) return o;
var lastPos = null;
var lastOff = null;
setInterval(function () {
if (o == null || o.length < 1) return o; // abort if element is non existend eny more
if (lastPos == null) lastPos = o.position();
if (lastOff == null) lastOff = o.offset();
var newPos = o.position();
var newOff = o.offset();
if (lastPos.top != newPos.top || lastPos.left != newPos.left) {
$(this).trigger('onPositionChanged', { lastPos: lastPos, newPos: newPos });
if (typeof (trigger) == "function") trigger(lastPos, newPos);
lastPos = o.position();
}
if (lastOff.top != newOff.top || lastOff.left != newOff.left) {
$(this).trigger('onOffsetChanged', { lastOff: lastOff, newOff: newOff});
if (typeof (trigger) == "function") trigger(lastOff, newOff);
lastOff= o.offset();
}
}, millis);
return o;
};
通过以下方式调用:
$("#<SOME_ID>").onPositionChanged(function(){alert("foobar")});
答案 1 :(得分:0)
这是我的解决方案,它基于willsteel解决方案。我必须监控width
和offsetWidth
的更改。即使元素因任何原因变得不可见/可见,这也会触发该功能。
请参阅以下更新代码:
jQuery.fn.onPositionChanged = function (trigger, millis) {
if (millis == null) millis = 100;
var o = $(this[0]); // our jquery object
if (o.length < 1) return o;
var lastPos = null;
var lastOff = null;
var lastWidth = null;
var lastOffWidth = null;
setInterval(function () {
if (o == null || o.length < 1) return o; // abort if element is non existend eny more
if (lastPos == null) lastPos = o.position();
if (lastOff == null) lastOff = o.offset();
if (lastWidth == null) lastWidth = o.width();
if (lastOffWidth == null) lastOffWidth = o[0].offsetWidth;
var newPos = o.position();
var newOff = o.offset();
var newWidth = o.width();
var newOffWidth = o[0].offsetWidth;
if (lastPos.top != newPos.top || lastPos.left != newPos.left) {
$(this).trigger('onPositionChanged', { lastPos: lastPos, newPos: newPos });
if (typeof (trigger) == "function") trigger(lastPos, newPos);
lastPos = o.position();
}
if (lastOff.top != newOff.top || lastOff.left != newOff.left) {
$(this).trigger('onPositionChanged', { lastOff: lastOff, newOff: newOff});
if (typeof (trigger) == "function") trigger(lastOff, newOff);
lastOff= o.offset();
}
if (lastWidth != newWidth) {
$(this).trigger('onPositionChanged', { lastWidth: lastWidth, newWidth: newWidth});
if (typeof (trigger) == "function") trigger(lastWidth, newWidth);
lastWidth= o.width();
}
if (lastOffWidth != newOffWidth) {
$(this).trigger('onPositionChanged', { lastOffWidth: lastOffWidth, newOffWidth: newOffWidth});
if (typeof (trigger) == "function") trigger(lastOffWidth, newOffWidth);
lastWidth= o.width();
}
}, millis);
return o;
};
答案 2 :(得分:0)
我上面的代码变体可以在多个对象上并且基于任何选择器运行,但不能与jQuery完全配合。
var onPositionChanged = function (selector,trigger, millis) {
if (millis == null) millis = 200;
setInterval(function(){
var o_s = jQuery(selector); // our jquery object
if (o_s.length < 1) return o_s;
for(var i = 0; i<o_s.length; i++)
{
var o = o_s.eq(i);
var lastPos = jQuery(o).attr("lastPos");
var lastOff = jQuery(o).attr("lastOff");
lastPos = ((lastPos == "" || lastPos == undefined) ? null : JSON.parse(lastPos));
lastOff = ((lastOff == "" || lastOff == undefined) ? null : JSON.parse(lastOff));
setTimeout(function (o) {
if (o == null || o.length < 1) return o; // abort if element is non existend eny more
if (lastPos == null) lastPos = o.position();
if (lastOff == null) lastOff = o.offset();
var newPos = o.position();
var newOff = o.offset();
if (lastPos.top != newPos.top || lastPos.left != newPos.left) {
jQuery(this).trigger('onPositionChanged', { lastPos: lastPos, newPos: newPos });
if (typeof (trigger) == "function") trigger(o,lastPos, newPos);
lastPos = o.position();
jQuery(o).attr("lastPos",JSON.stringify(lastPos));
}
if (lastOff.top != newOff.top || lastOff.left != newOff.left) {
jQuery(this).trigger('onOffsetChanged', { lastOff: lastOff, newOff: newOff});
if (typeof (trigger) == "function") trigger(o,lastOff, newOff);
lastOff= o.offset();
jQuery(o).attr("lastOff",JSON.stringify(lastOff));
}
}, millis,o);
}
},millis);
};
用法示例:
jQuery(document).ready(function(){
onPositionChanged(".grid-item:not(.d-none)",function(object){
var left_percentage = parseInt(jQuery(object).position().left / jQuery(object).parent().width() * 100);
var parent_width = jQuery(object).parent().width();
var percentage_of_parent = parseInt(jQuery(object).width() / parent_width * 100);
if(left_percentage > 74 && percentage_of_parent >= 25
|| left_percentage > 66 && percentage_of_parent >= 33
|| left_percentage > 49 && percentage_of_parent >= 50)
{
jQuery(object).find(".card").css("margin-right","0px");
jQuery(object).parent().masonry('layout');
}
if(left_percentage < 1)
{
jQuery(object).find(".card").css("margin-left","0px");
jQuery(object).parent().masonry('layout');
}
});
});