响应XUL元素的resize事件

由于GeckoXUL体系中缺乏resize事件支持,本文介绍了一种通过定时器监测元素尺寸变化的方法,并提供了XBL实现示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在Gecko XUL体系里,控件元素(button, label等)除了window之外是没有resize事件的,甚至到最近的31.0版本仍没有支持,我估计以后也很难见到元素的resize事件了。因为Mozilla的人当初设计XUL的时候,定义了hbox/vbox元素以及flex属性,甚至支持overflow和text-overflow样式,就是为了让开发人员少操心元素的尺寸变化问题,如果过分关注元素的resize事件,他们一定会说是开发人员自己的思路不对。但有时我在开发自己的扩展时,又不得不去关心元素的尺寸,比如一个vbox,里面有一些子元素,当这个vbox宽度小于一定值时,里面的子元素会在显示和排列方式上出现一些变化。这种情况下,就不得不想点办法来监控元素的尺寸了。

我想到的是最笨的办法,用计时器,interval尽可能小一点,但也不要太小,50毫秒差不多,每个时钟周期去检测元素的宽高,发现有变化时通知出去。为了让这个功能形成一个完整的模块,我用到了XBL,代码如下:

    <binding id="resizemonitor">
        <implementation>
            <field name="mTargetSize">null</field>
            <field name="mMonitorInterval">null</field>
            <field name="mIntervalTime">50</field>

            <constructor><![CDATA[
                this.mTargetSize = {
                    width: 0,
                    height: 0
                };

                this.mIntervalTime = parseInt(this.getAttribute("interval"), 10);
                if (!mIntervalTime) {
                    mIntervalTime = 50;
                }

                var attachType = this.getAttribute("attachType");
                if (attachType == "parent") {
                    this.attach(this.parentNode);
                } else if (attachType == "id") {
                    var targetId = this.getAttribute("targetId");
                    this.attach(document.getElementById(targetId));
                }
            ]]></constructor>

            <destructor><![CDATA[
                if (this.mMonitorInterval) {
                    window.clearInterval(this.mMonitorInterval);
                    this.mMonitorInterval = null;
                }
            ]]></destructor>

            <method name="attach">
                <parameter name="targetElt"/>
                <body><![CDATA[
                    if (this.mMonitorInterval) {
                        window.clearInterval(this.mMonitorInterval);
                        this.mMonitorInterval = null;
                    }

                    var me = this;
                    this.mMonitorInterval = window.setInterval(function() {
                        if (targetElt.style.display == "none") {
                            me.mTargetSize = {
                                width: 0,
                                height: 0
                            };
                            return;
                        }

                        var newWidth = targetElt.boxObject.width;
                        var newHeight = targetElt.boxObject.height;
                        if (newWidth != me.mTargetSize.width ||
                            newHeight != me.mTargetSize.height) {
                            var event = document.createEvent("Events");
                            event.initEvent("resize", true, true);
                            event.targetWidth = newWidth;
                            event.targetHeight = newHeight;
                            targetElt.dispatchEvent(event);

                            me.mTargetSize = {
                                width: newWidth,
                                height: newHeight
                            };
                        }
                    }, this.mIntervalTime);
                ]]></body>
            </method>
        </implementation>
    </binding>

在全局样式表中把这个resizemonitor用-moz-binding绑定一下,就可以使用这个元素标签了。可以把它放在所监视的元素的子结点下,也可以把它放到当前文档的任意一个位置,告诉它监控目标的id值就可以了。当发现目标的宽高发生改变,目标元素会触发一个resize事件,这个事件是自定义的。

用法1:

<textbox flex="1">
    <resizemonitor attachType="parent" interval="100/>
</textbox>

监控父元素textbox的尺寸变化,若发生改变,textbox将得到一个resize事件,

textbox.addEventListener("resize", function() {
    alert("size changed");
});

用法2:

<vbox id="mainbox"/>
<resizemonitor attachType="id" targetId="mainbox"/>
指定监控对象,计时器默认间隔为50毫秒。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值