Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
450 views
Welcome To Ask or Share your Answers For Others

1 Answer

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...


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...