Dynamic way to unbind dynamically binded XBL

若如初见. 提交于 2019-12-18 09:35:10

问题


I am applying a binding like this in a restartless add-on:

var css = '.findbar-container { -moz-binding:url("' + self.path.chrome + 'findbar.xml#matchword") }';
var cssEnc = encodeURIComponent(css);
var newURIParam = {
    aURL: 'data:text/css,' + cssEnc,
    aOriginCharset: null,
    aBaseURI: null
}
cssUri = Services.io.newURI(newURIParam.aURL, newURIParam.aOriginCharset, newURIParam.aBaseURI);
myServices.sss.loadAndRegisterSheet(cssUri, myServices.sss.USER_SHEET);

findbar.xml contents are:

<?xml version="1.0"?>
<bindings xmlns="http://www.mozilla.org/xbl" xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
    <binding id="matchword">
        <content>
            <children/>
            <xul:toolbarbutton anonid="matchwordbtn" accesskey="w" class="tabbable" label="Whole Word Only" tooltiptext="Match only whole words" oncommand="console.log('hi')" type="checkbox"/>
        </content>
    </binding>
</bindings>

This just adds a button to the FindBar labeled "Whole Word Only". But now to remove it, I am just unregistering the stylesheet with myServices.sss.unregisterSheet(cssUri, myServices.sss.USER_SHEET);, however this is not unbinding it.

An answer on ask.mozilla.org told me this is expected behavior, but offered no solution.

I was thinking maybe I should dynamically add the binding rather than via CSS, I didn't test this but it doesn't fit the 3 reasons for XBL updates:

  1. A bound element matches a style rule that specifies a different binding
  2. The element is removed from the bound document
  3. The element is destroyed (e.g., by closing the document)

The answer told me it's expected yet funky behavior.


回答1:


Well, I just remembered that I have some working code that does (re)bind different XBL bindings, essentially.

It goes like this:

  • There is a base binding, or not (in your case the original binding of .findbar-container).
  • Then I have multiple classes that define different -moz-bindings.
  • These classes are set and removed at runtime.

Since that works for me, it should in theory work for you:

  • In your style, do not have a rule for the element itself, but for a class, e.g.

    .findbar-container.myaddonclass { moz-binding: ... }
    
  • In your code, on load add that new class, e.g.

    Array.forEach(
      document.querySelectorAll(".findbar-container"),
      e => e.classList.add("myaddonclass")
      );
    
  • In your code, on unload remove the class again:

    Array.forEach(
      document.querySelectorAll(".findbar-container"),
      e => e.classList.remove("myaddonclass")
      );
    

This should force a CSS-rule reevaluation, and bindings reevaluation with that and hence fits the "A bound element matches a style rule that specifies a different binding" rule.

Of course, this sucks when not all elements you want to rebind are already present on load of your add-on, but MutationObserver could help with that...



来源:https://stackoverflow.com/questions/24403667/dynamic-way-to-unbind-dynamically-binded-xbl

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!