Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
434 views
in Technique[技术] by (71.8m points)

javascript - Dynamic way to unbind dynamically binded XBL

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

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

1 Reply

0 votes
by (71.8m points)

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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...