7

I need to listen to an elements relative position. This is particular useful for dynamic layouting issues. There is no option to listen for CSS styles of even position() or offset() attributes.

Why: The relative position can change if a sibling change its dimension inside dialogs or forms (re-layout). So for interactive forms this can help to use i.e. the maximum available height or width of the parent or something like that.

4

3 回答 3

13

此自定义 jquery 扩展通过计时器轮询侦听对象位置。Imo 没有计时器就没有办法解决这个问题,因为可以在根本不调用 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")});
于 2013-09-11T13:52:41.697 回答
0

这是我基于 willsteel 解决方案的解决方案。我必须监视对widthand的更改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;
};
于 2017-07-26T16:20:55.503 回答
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');
    }
});

});

于 2019-07-24T11:21:27.370 回答