【问题标题】:Trouble with XUL overlay, stringbundleset, getString is not a function, but createBundle method worksXUL 覆盖问题,stringbundleset,getString 不是函数,但 createBundle 方法有效
【发布时间】:2016-05-20 19:04:49
【问题描述】:

所以我正在开发一个旧的 XUL 覆盖插件并遇到了这个问题,并将其简化为一个最小的插件。想知道是否有人可以向我解释我做错了什么,如果我误解了什么,或者如何让它按预期工作。完整代码如下。在 FF 29.0b1 和 49.0a1 中测试,结果相同。

在主 XUL 文件中,我定义了一个 stringbundleset 和一个 stringbundle,两者都具有(很可能)唯一的 ID。在 JavaScript 文件中,我想通过元素 ID 简单地获取包(而不是集合),并使用 getString(或 getFormattedString)方法。在主 JavaScript 文件中,我有一个事件侦听器调用一个加载函数,该函数可以调用其他函数,包括一个 init 函数,我在其中放置了字符串抓取代码。所有的字符串变量都是用 var 全局定义的(在 init 函数之外)。问题是,我得到getString is not a function。此外,console.log() 在函数中的任何地方都不起作用,所以我什至无法检查应该保存返回字符串包的变量的值。

在我的插件中,我在 Options 和 About XUL 文件中使用了完全相同的模式,并且它可以正常工作,正如 MDN 文档所说的那样。所以我把它从示例代码中排除了。

如果尝试构建和测试,请注意在示例 JavaScript 代码中,我有尝试使用 XUL stringbundle 并失败的损坏块,并且使用 createBundle() 的纯 JavaScript 技术被注释掉了。这很容易用//* code /**/ 注释模式修改,只需删除第一个/ 并在另一个块上添加/ 并重建xpi。

以下是工作代码应创建的示例屏幕截图。该插件依赖于旧的状态栏。我使用了"The Addon Bar (Restored)" 附加组件。注意状态栏上的“TSBS”。右键单击“TSBS”,弹出一个菜单,顶部有Options。这些标签是从.dtd 文件中提取的。 Menu 是一个子菜单,其标签由tsbs.js 脚本设置,从.properties 文件中提取值。该示例显示它们是从纯 JS 方法中提取的。我正试图让它通过 XUL/DOM 方法工作。

我意识到 XUL 附加组件无论如何都会很快消亡。我意识到我不应该仅仅依赖状态栏。我意识到我应该只使用 JS-only 方法,因为它看起来更可靠。但我问这个是因为我注意到它并想从中学习。知道如何纠正或改进代码模式,或者这是一个已知问题还是常见的陷阱?

Directory tree:

test_string_bundle_set-1.0.0-fx
  +-- chrome
  |     +-- content
  |     |     +-- tsbs.js
  |     |     +-- tsbs.xul
  |     +-- locale
  |     |     +-- en-US
  |     |           +-- contents.rdf
  |     |           +-- tsbs.dtd
  |     |           +-- tsbs.properties
  +-- chrome.manifest
  +-- install.rdf

chrome.manifest:

overlay chrome://browser/content/browser.xul chrome://{00735700-7357-7357-7357-073570073570}/content/tsbs.xul

content {00735700-7357-7357-7357-073570073570} chrome/content/

locale {00735700-7357-7357-7357-073570073570} en-US chrome/locale/en-US/

install.rdf:

<?xml version="1.0" encoding="UTF-8"?>
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:em="http://www.mozilla.org/2004/em-rdf#">
    <Description about="urn:mozilla:install-manifest">
        <em:id>{00735700-7357-7357-7357-073570073570}</em:id>
        <em:version>1.0.0</em:version>
        <em:type>2</em:type>

        <em:name>Test String Bundle Sets</em:name>
        <em:description>Test String Bundle Sets</em:description>
        <em:creator>Quite A. Character</em:creator>

        <!--Firefox-->
        <em:targetApplication>
            <Description>
                <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
                <em:minVersion>29.0</em:minVersion>
                <em:maxVersion>49.*</em:maxVersion>
            </Description>
        </em:targetApplication>
    </Description>  
</RDF>

chrome/content/tsbs.js:

var tsbs_strings;

var tsbs_string_4;
var tsbs_string_5;
var tsbs_string_6;

function tsbs_load( ) {
    tsbs_init( );
    return true;
}

function tsbs_close( ) {
    return true;
}

window.addEventListener( 'load', tsbs_load, false );
window.addEventListener( 'close', tsbs_close, false );

function tsbs_init( ) {
    //* XUL/DOM method
    tsbs_strings    = document.getElementById( 'tsbs-strings' );

    console.log( 'TSBS->tsbs_init()->tsbs_strings: ' + typeof tsbs_strings );

    tsbs_string_4   = tsbs_strings.getString( 'tsbs.properties.string.4' );
    tsbs_string_5   = tsbs_strings.getString( 'tsbs.properties.string.5' );
    tsbs_string_6   = tsbs_strings.getString( 'tsbs.properties.string.6' );
    /**/
    /* JS-only method
    tsbs_strings    = Services.strings.createBundle( 'chrome://{00735700-7357-7357-7357-073570073570}/locale/tsbs.properties' );

    console.log( 'TSBS->tsbs_init()->tsbs_strings: ' + typeof tsbs_strings );

    tsbs_string_4   = tsbs_strings.GetStringFromName( 'tsbs.properties.string.4' );
    tsbs_string_5   = tsbs_strings.GetStringFromName( 'tsbs.properties.string.5' );
    tsbs_string_6   = tsbs_strings.GetStringFromName( 'tsbs.properties.string.6' );
    /**/

    document.getElementById( 'tsbs-item-4' ).label = tsbs_string_4;
    document.getElementById( 'tsbs-item-5' ).label = tsbs_string_5;
    document.getElementById( 'tsbs-item-6' ).label = tsbs_string_6;
}

chrome/content/tsbs.xul:

<?xml version="1.0" encoding="UTF-8"?>

<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>

<!DOCTYPE overlay SYSTEM "chrome://{00735700-7357-7357-7357-073570073570}/locale/tsbs.dtd">

<overlay id="tsbs-overlay" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">

    <script type="application/javascript" src="chrome://{00735700-7357-7357-7357-073570073570}/content/tsbs.js"/>

    <stringbundleset id="tsbs-stringset">
        <stringbundle id="tsbs-strings" src="chrome://{00735700-7357-7357-7357-073570073570}/locale/tsbs.properties"/>
    </stringbundleset>

    <statusbar id="status-bar">
        <statusbarpanel
            id="tsbs-display"
            label="&tsbs.dtd.statusbarpanel.display;"
            pack="end"
            context="tsbs-contextmenu"
        />
    </statusbar>

    <window id="main-window">
        <vbox id="tsbs-notifier">
            <popupset id="mainPopupSet">
                <menupopup id="tsbs-contextmenu" position="before_end">
                    <menuitem id="tsbs-options" label="&tsbs.dtd.options;"/>
                    <menuitem label="&tsbs.dtd.string.1;"/>
                    <menuitem label="&tsbs.dtd.string.2;"/>
                    <menuitem label="&tsbs.dtd.string.3;"/>
                    <menu id="tsbs-menu" label="&tsbs.dtd.menu;">
                        <menupopup id="tsbs-submenu">
                            <menuitem id="tsbs-item-4"/>
                            <menuitem id="tsbs-item-5"/>
                            <menuitem id="tsbs-item-6"/>
                        </menupopup>
                    </menu>
                </menupopup>
            </popupset>
        </vbox>
    </window>

</overlay>

chrome/locale/en-US/contents.rdf:

<?xml version="1.0" encoding="UTF-8"?>
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:chrome="http://www.mozilla.org/rdf/chrome#">
    <Seq about="urn:mozilla:locale:root">
        <li resource="urn:mozilla:locale:en-US"/>
    </Seq>
    <Description about="urn:mozilla:locale:en-US">
        <chrome:packages>
            <Seq about="urn:mozilla:locale:en-US:packages">
                <li resource="urn:mozilla:locale:en-US:{00735700-7357-7357-7357-073570073570}"/>
            </Seq>
        </chrome:packages>
    </Description>
</RDF>

chrome/locale/en-US/tsbs.dtd:

<!ENTITY tsbs.dtd.statusbarpanel.display    "TSBS"      >
<!ENTITY tsbs.dtd.options                   "Options"   >
<!ENTITY tsbs.dtd.menu                      "Menu"      >
<!ENTITY tsbs.dtd.string.1                  "One"       >
<!ENTITY tsbs.dtd.string.2                  "Two"       >
<!ENTITY tsbs.dtd.string.3                  "Three"     >

chrome/locale/en-US/tsbs.properties:

extensions.{00735700-7357-7357-7357-073570073570}.description=Test String Bundle Sets
tsbs.properties.string.4=four
tsbs.properties.string.5=five
tsbs.properties.string.6=six

【问题讨论】:

    标签: firefox-addon xul


    【解决方案1】:

    我相信这是你的问题:

    <stringbundleset id="tsbs-stringset">
    

    在 XUL 覆盖中,如果 &lt;overlay&gt; 的直接子级具有 ID,则它应该与基础文档中的元素匹配。 If it does, its contents is inserted under the matching element. If it doesn't this part of an overlay is ignored.

    browser.xul中已有的stringbundleset can be matched using:

    <stringbundleset id="stringbundleset">
    

    另外,我不相信有一个“关闭”事件(使用“卸载”),而且你不需要 content.rdf,因为 Firefox 2 左右。关于 console.log() 不起作用 - 您检查的是 Browser Console,而不是 Web 控制台,对吧?

    【讨论】:

    • 啊!我知道某些标签必须匹配覆盖,但我不确定哪些标签。这是 JavaScript 中的逆逻辑,您尝试使用唯一名称来避免重新分配现有变量。但是通过将脚本包装在一个对象中会更好地解决这个问题。无论如何,我必须匆忙更改覆盖 XUL 中的 stringbundleset ID。谢谢你的提示,很高兴它很简单。很高兴我可以摆脱那些内容.rdf。少了一件需要维护的事情。也感谢您的提示!所以我可以查看chrome://browser/content/browser.xul 以确保我的 ID 重叠。
    • 啊,是的,我确实检查了浏览器控制台,忘了说。 Ctrl-Shift-J 为我带来了它,所有日志记录选项都打开了(Net + req/resp 主体、CSS、JS、安全、日志记录)。我回到这里是因为我的主要插件突然又开始这样做了。真的让我很烦。 XUL 已正确设置,因此错误在其他地方。我的演示有效,而真正的代码却没有,它们看起来完全一样,而且我无法记录。 &lt;script&gt; 包含 4 个 .js 文件,以前是 2-3 个。也许订单很重要,他们现在加载不正常?不知道还能尝试什么。
    • 决定使用 XUL stringbundleset 不值得浪费时间。只需在 JS 中处理这一切,它可以按预期工作,否则我至少会收到错误并可以插入 console.logs 以查看它在做什么。
    • @user314159 我会尝试alert 或其他方式来修改用户界面。或者甚至可能是浏览器调试器——我们现在拥有精美的工具,与过去不同!我发现很难相信覆盖中被忽略的标签 (&lt;stringbundleset id="wrong-id"&gt;) 或尝试访问不存在的元素 (tsbs_strings = document.getElementById( 'tsbs-strings' );) 会以任何方式影响 console.log,所以你真的很奇怪将此归咎于 XUL stringbundleset...
    • alert 给出了一个关于尝试使用没有窗口或奇怪的用户界面调用的错误。我尝试打开调试器,但它只让我调试当前打开的选项卡( about:addons ),我不知道如何让调试器将自己附加到附加帖子“onload”的活动中,但预先“初始化”状态。问题出在其他 JS 代码中,但对 bundleset 的依赖阻止了 JS 抛出的有用错误消息,并引导我走上修复它的道路。当其他代码也可以工作时,捆绑包很棒。但是每次调试都浪费时间切换到纯 JS 不值得。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-25
    相关资源
    最近更新 更多