<?xml version="1.0"?>

<!-- ***** BEGIN LICENSE BLOCK *****
   -
   - CSS Selector Builder
   -
   - (c) Copyright Disruptive Innovations SARL 2005
   - All Rights Reserved.
   -
   - ***** END LICENSE BLOCK ***** -->
<!DOCTYPE bindings [
<!ENTITY of.label "of">
<!ENTITY childOf.label "child of">
<!ENTITY descendantOf.label "descendant of">
<!ENTITY following.label  "following">
<!ENTITY followingDirectlt.label "following directly">

<!ENTITY allElements.label "all elements">
<!ENTITY allElementsOfType.label "all elements of type">

<!ENTITY ofClass.label "of class">
<!ENTITY ofID.label "of ID">
<!ENTITY holdingAttribute.label "holding attribute">
<!ENTITY ofLanguage.label "of language">
<!ENTITY hover.label "hovered by the pointer">
<!ENTITY focus.label "having focus">
<!ENTITY active.label "activated">
<!ENTITY target.label "target of the URL">
<!ENTITY link.label "an unvisited link">
<!ENTITY visited.label "a visited link">
<!ENTITY root.label "root of the document">
<!ENTITY empty.label "empty">
<!ENTITY firstChild.label "first child">
<!ENTITY lastChild.label "last child">
<!ENTITY nthChild.label "n-th child">
<!ENTITY nthLastChild.label "n-th last child">
<!ENTITY onlyChild.label "only child">
<!ENTITY firstOfType.label "first of type">
<!ENTITY lastOfType.label "last of type">
<!ENTITY nthOfType.label "n-th of type">
<!ENTITY nthLastOfType.label "n-th last of type">
<!ENTITY only.ofType.label "only of type">

<!ENTITY valueIs.label "whose value is">
<!ENTITY valueBegins.label "whose value begins with">
<!ENTITY valueEnds.label "whose value ends with">
<!ENTITY valueContains.label "whose value contains">
]>

<bindings id="selectorBuilderBindings"
          xmlns="http://www.mozilla.org/xbl"
          xmlns:html="http://www.w3.org/1999/xhtml"
          xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
          xmlns:xbl="http://www.mozilla.org/xbl">

  <binding id="SimpleSelectorSequence">
    <content>
      <xul:label value="&of.label;" style="color: red" anonid="ofLabel"/>
      <xul:menulist style="text-align: right" anonid="combinatorMenulist"
                    oncommand="this.parentNode.Update();" value=" > ">
        <xul:menupopup>
          <xul:menuitem label="&childOf.label;" value=" > " selected="true"/>
          <xul:menuitem label="&descendantOf.label;" value=" "/>
          <xul:menuitem label="&following.label;" value=" ~ "/>
          <xul:menuitem label="&followingDirectlt.label;" value=" + "/>
        </xul:menupopup>
      </xul:menulist>
      <xul:menulist oncommand="this.parentNode.SetValue(this.value);" value="*">
        <xul:menupopup>
          <xul:menuitem label="&allElements.label;" value="*" selected="true"/>
          <xul:menuitem label="&allElementsOfType.label;" value="elt"/>
        </xul:menupopup>
      </xul:menulist>
      <xul:textbox size="4" anonid="textbox" style="display: none"
                   oninput="this.parentNode.Update();"/>
    </content>

    <field name="mValue">null</field>

    <implementation>
      <constructor>
        <![CDATA[
          if (this.getAttribute("selectorSubject"))
          {
            this.mOfLabel.removeAttribute("style");
            this.mCombinatorMenulist.setAttribute("style", "display: none;");
          }
          else
          {
            this.mCombinatorMenulist.removeAttribute("style");
            this.mOfLabel.setAttribute("style", "display: none;");
          }
          this.mValue = "*";
        ]]>
      </constructor>      

      <property name="mTextbox">
        <getter>
        <![CDATA[
          return document.getAnonymousElementByAttribute(this, "anonid", "textbox");
        ]]>
        </getter>
      </property>

      <property name="mOfLabel">
        <getter>
        <![CDATA[
          return document.getAnonymousElementByAttribute(this, "anonid", "ofLabel");
        ]]>
        </getter>
      </property>

      <property name="mCombinatorMenulist">
        <getter>
        <![CDATA[
          return document.getAnonymousElementByAttribute(this, "anonid", "combinatorMenulist");
        ]]>
        </getter>
      </property>

      <method name="Update">
        <body>
          <![CDATA[
            window.Compute();
          ]]>
        </body>
      </method>

      <method name="GetCombinator">
        <body>
          <![CDATA[
            var menulist = document.getAnonymousElementByAttribute(this, "anonid", "combinatorMenulist");
            return (this.getAttribute("selectorSubject") ? "" : menulist.value );
          ]]>
        </body>
      </method>

      <method name="GetSelector">
        <body>
          <![CDATA[
            return (this.mValue == "*" ? "*" : (this.mTextbox.value ? this.mTextbox.value : "*"));
          ]]>
        </body>
      </method>

      <method name="SetValue">
        <parameter name="value"/>
        <body>
          <![CDATA[
            this.mValue = value;
            if (value == "*")
              this.mTextbox.setAttribute("style", "display: none");
            else
              this.mTextbox.removeAttribute("style");
            window.Compute();
          ]]>
        </body>
      </method>

    </implementation>
  </binding>

  <binding id="SimpleSelector">

  <content>
    <spacer/>
    <xul:hbox align="center">
      <xul:checkbox label="not" anonid="notCheckbox" oncommand="this.parentNode.parentNode.Update();"/>
      <xul:menulist oncommand="this.parentNode.parentNode.SetValue(this.value);">
        <xul:menupopup>
          <xul:menuitem label="&ofClass.label;"                   value="classSelector"/>
          <xul:menuitem label="&ofID.label;"                      value="IDSelector"/>
          <xul:menuitem label="&holdingAttribute.label;"          value="attrSelector"/>
          <xul:menuitem label="&ofLanguage.label;"                value="langSelector"/>
          <xul:menuseparator/>
          <xul:menuitem label="&hover.label;"     value="hoverPseudo"/>
          <xul:menuitem label="&focus.label;"               value="focusPseudo"/>
          <xul:menuitem label="&active.label;"                  value="activePseudo"/>
          <xul:menuitem label="&target.label;"          value="targetPseudo"/>
          <xul:menuseparator/>
          <xul:menuitem label="&link.label;"          value="linkPseudo"/>
          <xul:menuitem label="&visited.label;"             value="visitedPseudo"/>
          <xul:menuseparator/>
          <xul:menuitem label="&root.label;"       value="rootPseudo"/>
          <xul:menuitem label="&empty.label;"                      value="emptyPseudo"/>
          <xul:menuseparator/>
          <xul:menuitem label="&firstChild.label;"                value="firstChildPseudo"/>
          <xul:menuitem label="&lastChild.label;"                 value="lastChildPseudo"/>
          <xul:menuitem label="&nthChild.label;"                 value="nthChildPseudo"/>
          <xul:menuitem label="&nthLastChild.label;"            value="nthLastChildPseudo"/>
          <xul:menuitem label="&onlyChild.label;"                 value="onlyChildPseudo"/>
          <xul:menuseparator/>
          <xul:menuitem label="&firstOfType.label;"              value="firstOfTypePseudo"/>
          <xul:menuitem label="&lastOfType.label;"               value="lastOfTypePseudo"/>
          <xul:menuitem label="&nthOfType.label;"               value="nthOfTypePseudo"/>
          <xul:menuitem label="&nthLastOfType.label;"          value="nthOfLastTypePseudo"/>
          <xul:menuitem label="&only.ofType.label;"               value="onlyOfTypePseudo"/>
        </xul:menupopup>
      </xul:menulist>
    </xul:hbox>
    <xul:textbox anonid="nameBox" size="4" oninput="this.parentNode.Update();"/>
    <xul:menulist anonid="conditionMenulist" style="display: none;" oncommand="this.parentNode.Update();">
      <xul:menupopup>
        <xul:menuitem label=" " value=""/>
        <xul:menuitem label="&valueIs.label;"             value="="/>
        <xul:menuitem label="&valueBegins.label;"    value="^="/>
        <xul:menuitem label="&valueEnds.label;"      value="$="/>
        <xul:menuitem label="&valueContains.label;"       value="*="/>
      </xul:menupopup>
    </xul:menulist>
    <xul:textbox anonid="valueBox" size="4" style="display: none;" oninput="this.parentNode.Update();"/>
  </content>

    <implementation>
      <constructor>
        <![CDATA[
          this.mValue = "classSelector";
        ]]>
      </constructor>      


    <field name="mValue">"*"</field>

      <property name="mNotCheckbox">
        <getter>
        <![CDATA[
          return document.getAnonymousElementByAttribute(this, "anonid", "notCheckbox");
        ]]>
        </getter>
      </property>

      <property name="mNameBox">
        <getter>
        <![CDATA[
          return document.getAnonymousElementByAttribute(this, "anonid", "nameBox");
        ]]>
        </getter>
      </property>

      <property name="mConditionMenulist">
        <getter>
        <![CDATA[
          return document.getAnonymousElementByAttribute(this, "anonid", "conditionMenulist");
        ]]>
        </getter>
      </property>

      <property name="mValueBox">
        <getter>
        <![CDATA[
          return document.getAnonymousElementByAttribute(this, "anonid", "valueBox");
        ]]>
        </getter>
      </property>

      <method name="Update">
        <body>
          <![CDATA[
            window.Compute();
          ]]>
        </body>
      </method>

      <method name="GetSelector">
        <body>
          <![CDATA[
            var not = this.mNotCheckbox.checked;
            var value = "";

            var menulist = document.getAnonymousElementByAttribute(this, "anonid", "conditionMenulist");
            switch (this.mValue)
            {
              case "attrSelector":
                if (this.mNameBox.value)
                  switch (menulist.value)
                  {
                    case "":
                      value = "[" + this.mNameBox.value + "]";
                      break;
                    default:
                      value = "[" + this.mNameBox.value;
                      if (this.mValueBox.value)
                        value += menulist.value + this.mValueBox.value;
                      value += "]";
                      break;
                  }
                break;
                
              case "classSelector":          value = (this.mNameBox.value ? "." + this.mNameBox.value : ""); break;
              case "IDSelector":             value = (this.mNameBox.value ? "#" + this.mNameBox.value : ""); break;
              case "nthChildPseudo":         value = (this.mNameBox.value ? ":nth-child(" + this.mNameBox.value + ")" : ""); break;
              case "nthLastChildPseudo":     value = (this.mNameBox.value ? ":nth-last-child(" + this.mNameBox.value + ")" : ""); break;
              case "nthOfTypePseudo":        value = (this.mNameBox.value ? ":nth-of-type(" + this.mNameBox.value + ")" : ""); break;
              case "nthOfLastTypePseudo":    value = (this.mNameBox.value ? ":nth-last-of-type(" + this.mNameBox.value + ")" : ""); break;
              case "langSelector":           value = (this.mNameBox.value ? ":lang(" + this.mNameBox.value + ")" : ""); break;

              default:
              case "hoverPseudo":            value = ":hover"; break;
              case "focusPseudo":            value = ":focus"; break;
              case "activePseudo":           value = ":active"; break;
              case "targetPseudo":           value = ":target"; break;
              case "linkPseudo":             value = ":link"; break;
              case "visitedPseudo":          value = ":visited"; break;
              case "rootPseudo":             value = ":root"; break;
              case "emptyPseudo":            value = ":empty"; break;
              case "firstChildPseudo":       value = ":first-child"; break;
              case "lastChildPseudo":        value = ":last-child"; break;
              case "onlyChildPseudo":        value = ":only-child"; break;
              case "firstOfTypePseudo":      value = ":first-of-type"; break;
              case "lastOfTypePseudo":       value = ":last-of-type"; break;
              case "onlyOfTypePseudo":       value = ":only-of-type"; break;
                break;
            }
            if (not && value)
              return ":not(" + value + ")";
            return value;
          ]]>
        </body>
      </method>

      <method name="SetValue">
        <parameter name="value"/>
        <body>
          <![CDATA[
            this.mValue = value;
            var nameBoxStyle           = "display: none";
            var conditionMenulistStyle = "display: none";
            var valueBoxStyle          = "display: none";
            switch (value)
            {
              case "attrSelector":
                nameBoxStyle = "";
                conditionMenulistStyle = "";
                valueBoxStyle = "";
                break;
                
              case "classSelector":
              case "IDSelector":
              case "nthChildPseudo":
              case "nthLastChildPseudo":
              case "nthOfTypePseudo":
              case "nthOfLastTypePseudo":
              case "langSelector":
                nameBoxStyle = "";
                break;

              default:
              case "hoverPseudo":
              case "focusPseudo":
              case "activePseudo":
              case "targetPseudo":
              case "linkPseudo":
              case "visitedPseudo":
              case "rootPseudo":
              case "emptyPseudo":
              case "firstChildPseudo":
              case "lastChildPseudo":
              case "onlyChildPseudo":
              case "firstOfTypePseudo":
              case "lastOfTypePseudo":
              case "onlyOfTypePseudo":
                break;
            }
            this.mNameBox.setAttribute("style", nameBoxStyle);
            this.mConditionMenulist.setAttribute("style", conditionMenulistStyle);
            this.mValueBox.setAttribute("style", valueBoxStyle);
            window.Compute();
          ]]>
        </body>
      </method>

    </implementation>
  </binding>
</bindings>
