Search code examples
firefoxfirefox-addonxulthunderbird-addonxbl

Crop for checkbox and radio XUL elements doesn't work


I'm trying to crop the very long label of a checkbox so it will fit in boundaries set by it's parent node. I can't figure out why the crop attribute is totally ignored:

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

<dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" align="center" flex="1">
    <vbox style="width: 35em; overflow: hidden;" flex="1">
        <hbox>
            <checkbox crop="center" style="max-width: 35em;" label="1415926535897932384626433832795028841971693993751058209749445923 0781640628620899862803482534211706798214808651328230664709384460 9550582231725359408128481117450284102701938521105559644622948954 9303819644288109756659334461284756482337867831652712019091456485 6692346034861045432664821339360726024914127372458700660631558817 4881520920962829254091715364367892590360011330530548820466521384 1469519415116094330572703657595919530921861173819326117931051185 4807446237996274956735188575272489122793818301194912983367336244 0656643086021394946395224737190702179860943702770539217176293176 7523846748184676694051320005681271452635608277857713427577896091 7363717872146844090122495343014654958537105079227968925892354201 9956112129021960864034418159813629774771309960518707211349999998 3729780499510597317328160963185950244594553469083026425223082533 4468503526193118817101000313783875288658753320838142061717766914 7303598253490428755468731159562863882353787593751957781857780532 171226806613001927876611195909216420198"/>
        </hbox>
    </vbox>
</dialog>

Not only doesn't it crop the label, but it also wraps it into multiple lines.

Any ideas?


Solution

  • As you have determined, this is a bug in Firefox. You have already filed a bug about it. Now that I read the bug, I see that you have already determined one method of getting this to work. Prior to seeing that bug, I had already written the code needed to get crop on <checkbox> (and <radio>) working for you.

    If you already have code that is working for you, then please post an answer.

    The issue is that for both <checkbox> and <radio> the XBL causes a <text> node to be created as a child of the <label> containing the text for the <checkbox> or <radio>. However, the nsIDOMXULDescriptionElement interface, which is what does the cropping, is implemented for the value attribute of <label> elements, but not for child <text> nodes.

    The two solutions are to either implement nsIDOMXULDescriptionElement for the <text> nodes, or use the value attribute of the label for the text when the crop attribute exists (or perhaps only when it is valid). The reason a child <text> node is used is to permit the <label> to be multiple wrapped lines when the text is too long to fit horizontally. In other words, creating the <text> node is intended in order to permit functionality other than crop.

    Looking through the XBL for XUL it appears that this construct is used in multiple elements. I have not investigated if using this construct causes problems in other elements for things other than crop.

    For <checkbox> and <radio> the XBL is contained a a few different files.

    The line that is needed for <checkbox> (in binding ID's checkbox and checkbox-crop-with-spacing) is:

    <xul:label class="checkbox-label" xbl:inherits="value=label,accesskey,crop" flex="1"/>
    

    instead of :

    <xul:label class="checkbox-label" xbl:inherits="xul:text=label,accesskey,crop" flex="1"/>
    

    For radio (multiple files) the line which is needed (for binding ID's radio and radio-with-spacing) is:

    <xul:label class="radio-label" xbl:inherits="value=label,accesskey,crop" flex="1"/>
    

    instead of:

    <xul:label class="radio-label" xbl:inherits="xul:text=label,accesskey,crop" flex="1"/>
    

    Now, because we want the ability have both cropped labels and multi-line labels, we don't want to just change these lines. We want to create additional XBL bindings that are only applied when the crop attribute is present.

    The new bindings (checkbox_radio_crop.xml):

    <?xml version="1.0"?>
    <bindings id="checkboxAndRadioCropBindings"
       xmlns="http://www.mozilla.org/xbl"
       xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
       xmlns:xbl="http://www.mozilla.org/xbl">
    
      <binding id="checkbox-crop"
               extends="chrome://global/content/bindings/checkbox.xml#checkbox">
        <content>
          <xul:image class="checkbox-check" xbl:inherits="checked,disabled"/>
          <xul:hbox class="checkbox-label-box" flex="1">
            <xul:image class="checkbox-icon" xbl:inherits="src"/>
            <xul:label class="checkbox-label"
                       xbl:inherits="value=label,accesskey,crop" flex="1"/>
          </xul:hbox>
        </content>
      </binding>
    
      <binding id="checkbox-crop-with-spacing"
               extends="chrome://global/content/bindings/checkbox.xml#checkbox">
        <content>
          <xul:hbox class="checkbox-spacer-box">
            <xul:image class="checkbox-check" xbl:inherits="checked,disabled"/>
          </xul:hbox>
          <xul:hbox class="checkbox-label-center-box" flex="1">
            <xul:hbox class="checkbox-label-box" flex="1">
              <xul:image class="checkbox-icon" xbl:inherits="src"/>
              <xul:label class="checkbox-label"
                         xbl:inherits="value=label,accesskey,crop" flex="1"/>
            </xul:hbox>
          </xul:hbox>
        </content>
      </binding>
    
    
      <binding id="radio-crop"
               extends="chrome://global/content/bindings/radio.xml#radio">
        <content>
          <xul:hbox class="radio-check-box1" xbl:inherits="selected,checked,disabled">
            <xul:hbox class="radio-check-box2" flex="1">
              <xul:image class="radio-check" xbl:inherits="selected,checked,disabled"/>
            </xul:hbox>
          </xul:hbox>
          <xul:hbox class="radio-label-box" align="center" flex="1">
            <xul:image class="radio-icon" xbl:inherits="src"/>
            <xul:label class="radio-label"
                       xbl:inherits="value=label,accesskey,crop" flex="1"/>
          </xul:hbox>
        </content>
      </binding>
    
      <binding id="radio-crop-with-spacing"
               extends="chrome://global/skin/globalBindings.xml#radio">
        <content>
          <xul:hbox class="radio-spacer-box">
            <xul:hbox class="radio-check-box1" xbl:inherits="selected,checked,disabled">
              <xul:hbox class="radio-check-box2" flex="1">
                <xul:image class="radio-check" xbl:inherits="selected,checked,disabled"/>
              </xul:hbox>
            </xul:hbox>
          </xul:hbox>
          <xul:hbox class="radio-label-center-box" flex="1">
            <xul:hbox class="radio-label-box" flex="1">
              <xul:image class="radio-icon" xbl:inherits="src"/>
              <xul:label class="radio-label"
                         xbl:inherits="value=label,accesskey,crop" flex="1"/>
            </xul:hbox>
          </xul:hbox>
        </content>
      </binding>
    
    </bindings>
    

    then the CSS to apply the bindings when the crop attribute exists (checkbox_radio_crop.css):

    checkbox[crop] {
        -moz-binding: url('checkbox_radio_crop.xml#checkbox-crop');
    }
    checkbox-with-spacing[crop] {
        -moz-binding: url('checkbox_radio_crop.xml#checkbox-crop-with-spacing');
    }
    radio[crop] {
        -moz-binding: url('checkbox_radio_crop.xml#radio-crop');
    }
    radio-with-spacing[crop] {
        -moz-binding: url('checkbox_radio_crop.xml#radio-crop-with-spacing');
    }
    

    Then we can test it with some XUL that is based on what you provided in the question:

    <?xml version="1.0"?>
    <?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
    <?xml-stylesheet href="checkbox_radio_crop.css" type="text/css"?>
    
    <dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" align="center" flex="1">
        <groupbox >
            <caption label="Test checkboxes"/>
            <checkbox crop="start"  style="max-width: 35em;" label="crop=&quot;start&quot; 1415926535897932384626433832795028841971693993751058209749445923 0781640628620899862803482534211706798214808651328230664709384460 9550582231725359408128481117450284102701938521105559644622948954 9303819644288109756659334461284756482337867831652712019091456485 6692346034861045432664821339360726024914127372458700660631558817 4881520920962829254091715364367892590360011330530548820466521384 1469519415116094330572703657595919530921861173819326117931051185 4807446237996274956735188575272489122793818301194912983367336244 0656643086021394946395224737190702179860943702770539217176293176 7523846748184676694051320005681271452635608277857713427577896091 7363717872146844090122495343014654958537105079227968925892354201 9956112129021960864034418159813629774771309960518707211349999998 3729780499510597317328160963185950244594553469083026425223082533 4468503526193118817101000313783875288658753320838142061717766914 7303598253490428755468731159562863882353787593751957781857780532 171226806613001927876611195909216420198    crop=&quot;start&quot; "/>
            <checkbox crop="center" style="max-width: 35em;" label="crop=&quot;center&quot; 1415926535897932384626433832795028841971693993751058209749445923 0781640628620899862803482534211706798214808651328230664709384460 9550582231725359408128481117450284102701938521105559644622948954 9303819644288109756659334461284756482337867831652712019091456485 6692346034861045432664821339360726024914127372458700660631558817 4881520920962829254091715364367892590360011330530548820466521384 1469519415116094330572703657595919530921861173819326117931051185 4807446237996274956735188575272489122793818301194912983367336244 0656643086021394946395224737190702179860943702770539217176293176 7523846748184676694051320005681271452635608277857713427577896091 7363717872146844090122495343014654958537105079227968925892354201 9956112129021960864034418159813629774771309960518707211349999998 3729780499510597317328160963185950244594553469083026425223082533 4468503526193118817101000313783875288658753320838142061717766914 7303598253490428755468731159562863882353787593751957781857780532 171226806613001927876611195909216420198"/>
            <checkbox crop="end"    style="max-width: 35em;" label="crop=&quot;end&quot; 1415926535897932384626433832795028841971693993751058209749445923 0781640628620899862803482534211706798214808651328230664709384460 9550582231725359408128481117450284102701938521105559644622948954 9303819644288109756659334461284756482337867831652712019091456485 6692346034861045432664821339360726024914127372458700660631558817 4881520920962829254091715364367892590360011330530548820466521384 1469519415116094330572703657595919530921861173819326117931051185 4807446237996274956735188575272489122793818301194912983367336244 0656643086021394946395224737190702179860943702770539217176293176 7523846748184676694051320005681271452635608277857713427577896091 7363717872146844090122495343014654958537105079227968925892354201 9956112129021960864034418159813629774771309960518707211349999998 3729780499510597317328160963185950244594553469083026425223082533 4468503526193118817101000313783875288658753320838142061717766914 7303598253490428755468731159562863882353787593751957781857780532 171226806613001927876611195909216420198"/>
            <checkbox               style="max-width: 35em;" label="no crop 1415926535897932384626433832795028841971693993751058209749445923 0781640628620899862803482534211706798214808651328230664709384460 9550582231725359408128481117450284102701938521105559644622948954 9303819644288109756659334461284756482337867831652712019091456485 6692346034861045432664821339360726024914127372458700660631558817 4881520920962829254091715364367892590360011330530548820466521384 1469519415116094330572703657595919530921861173819326117931051185 4807446237996274956735188575272489122793818301194912983367336244 0656643086021394946395224737190702179860943702770539217176293176 7523846748184676694051320005681271452635608277857713427577896091 7363717872146844090122495343014654958537105079227968925892354201 9956112129021960864034418159813629774771309960518707211349999998 3729780499510597317328160963185950244594553469083026425223082533 4468503526193118817101000313783875288658753320838142061717766914 7303598253490428755468731159562863882353787593751957781857780532 171226806613001927876611195909216420198"/>
        </groupbox>
        <groupbox>
            <caption label="Test radios"/>
            <radiogroup>
                <radio crop="start"  label="crop=&quot;start&quot; 1415926535897932384626433832795028841971693993751058209749445923 0781640628620899862803482534211706798214808651328230664709384460 9550582231725359408128481117450284102701938521105559644622948954 9303819644288109756659334461284756482337867831652712019091456485 6692346034861045432664821339360726024914127372458700660631558817 4881520920962829254091715364367892590360011330530548820466521384 1469519415116094330572703657595919530921861173819326117931051185 4807446237996274956735188575272489122793818301194912983367336244 0656643086021394946395224737190702179860943702770539217176293176 7523846748184676694051320005681271452635608277857713427577896091 7363717872146844090122495343014654958537105079227968925892354201 9956112129021960864034418159813629774771309960518707211349999998 3729780499510597317328160963185950244594553469083026425223082533 4468503526193118817101000313783875288658753320838142061717766914 7303598253490428755468731159562863882353787593751957781857780532 171226806613001927876611195909216420198    crop=&quot;start&quot;" />
                <radio crop="center" label="crop=&quot;center&quot; 1415926535897932384626433832795028841971693993751058209749445923 0781640628620899862803482534211706798214808651328230664709384460 9550582231725359408128481117450284102701938521105559644622948954 9303819644288109756659334461284756482337867831652712019091456485 6692346034861045432664821339360726024914127372458700660631558817 4881520920962829254091715364367892590360011330530548820466521384 1469519415116094330572703657595919530921861173819326117931051185 4807446237996274956735188575272489122793818301194912983367336244 0656643086021394946395224737190702179860943702770539217176293176 7523846748184676694051320005681271452635608277857713427577896091 7363717872146844090122495343014654958537105079227968925892354201 9956112129021960864034418159813629774771309960518707211349999998 3729780499510597317328160963185950244594553469083026425223082533 4468503526193118817101000313783875288658753320838142061717766914 7303598253490428755468731159562863882353787593751957781857780532 171226806613001927876611195909216420198"/>
                <radio crop="end"    label="crop=&quot;end&quot; 1415926535897932384626433832795028841971693993751058209749445923 0781640628620899862803482534211706798214808651328230664709384460 9550582231725359408128481117450284102701938521105559644622948954 9303819644288109756659334461284756482337867831652712019091456485 6692346034861045432664821339360726024914127372458700660631558817 4881520920962829254091715364367892590360011330530548820466521384 1469519415116094330572703657595919530921861173819326117931051185 4807446237996274956735188575272489122793818301194912983367336244 0656643086021394946395224737190702179860943702770539217176293176 7523846748184676694051320005681271452635608277857713427577896091 7363717872146844090122495343014654958537105079227968925892354201 9956112129021960864034418159813629774771309960518707211349999998 3729780499510597317328160963185950244594553469083026425223082533 4468503526193118817101000313783875288658753320838142061717766914 7303598253490428755468731159562863882353787593751957781857780532 171226806613001927876611195909216420198"/>
                <radio               label="no crop 1415926535897932384626433832795028841971693993751058209749445923 0781640628620899862803482534211706798214808651328230664709384460 9550582231725359408128481117450284102701938521105559644622948954 9303819644288109756659334461284756482337867831652712019091456485 6692346034861045432664821339360726024914127372458700660631558817 4881520920962829254091715364367892590360011330530548820466521384 1469519415116094330572703657595919530921861173819326117931051185 4807446237996274956735188575272489122793818301194912983367336244 0656643086021394946395224737190702179860943702770539217176293176 7523846748184676694051320005681271452635608277857713427577896091 7363717872146844090122495343014654958537105079227968925892354201 9956112129021960864034418159813629774771309960518707211349999998 3729780499510597317328160963185950244594553469083026425223082533 4468503526193118817101000313783875288658753320838142061717766914 7303598253490428755468731159562863882353787593751957781857780532 171226806613001927876611195909216420198"/>
            </radiogroup>
        </groupbox>
    </dialog>
    

    This when the above test XUL is used to open a dialog window the following is displayed:

    checkbox and radio test dialog window

    To make it work in your XUL you will need the files checkbox_radio_crop.xml and checkbox_radio_crop.css. You will then need to add the line:

    <?xml-stylesheet href="checkbox_radio_crop.css" type="text/css"?>
    

    to your XUL. Obviously, the files are currently using relative URLs to reference the files. Thus, they will need to be located in the same directory as your XUL. You can, of course, place the files anywhere you desire by using fully qualified chrome:// URLs to reference the needed files in both the CSS and your XUL.

    While the above changes could be put into Firefox, the places where they need to go are actually across multiple files. Thus, it is somewhat more complicated. I'll see about updating the Mozilla bug with the code that would need to change for a fix. In addition, I'll work on the MDN documentation for crop to make it clear that it is not working in <checkbox> & <radio> elements. I'll also provide this code as a polyfill.