Xpoint
   [напомнить пароль]

Существует ли стандартный компонент типа SpinEdit

2005-11-24 18:12:43 [обр] Viacheslav Besedin [досье]
Привет уважаемому XUL сообществу.
Подскажите пожалуйста существует ли в Mozilla такой контрол поле ввода с кнопочками стрелками сбоку, клик по которым наращивает (уменьшает) на определенную величину значение в поле ввода. Если такого контрола нет, то направьте, пожалуйста, в какую сторону копать, чтобы реализовать данную функциональность.
Заранее благодарен.
спустя 52 минуты [обр] Владимир Палант [досье]

<spinbuttons> пока еще не работает: bug 155053

Так что придется делать самому, благо это несложно. У меня получился такой вот XBL:

<?xml version="1.0" encoding="UTF-8"?>

<bindings id="spinboxBindings"
   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="spinbox">
    <resources>
      <stylesheet src="spinbox.css"/>
    </resources>

    <content>
      <xul:hbox flex="1">
        <xul:textbox id="textField" flex="1" xbl:inherits="type,value,maxlength,timeout,oninput,onchange,disabled"/>
        <xul:vbox align="center">
          <xul:image id="upButton" class="up"/>
          <xul:image id="downButton" class="down"/>
        </xul:vbox>
      </xul:hbox>
    </content>

    <implementation>
      <constructor>
        <![CDATA[
          if (this.getAttribute('onup'))
            this.setAttribute('onup', this.getAttribute('onup'));
          if (this.getAttribute('ondown'))
            this.setAttribute('ondown', this.getAttribute('ondown'));
        ]]>
      </constructor>
      <property name="value"
                onget="return document.getAnonymousElementByAttribute(this, 'id', 'textField').value"
                onset="document.getAnonymousElementByAttribute(this, 'id', 'textField').value = val"/>
    </implementation>

    <handlers>
      <handler event="DOMAttrModified">
      <![CDATA[
        if (event.target == this && (event.attrName == 'onup' || event.attrName == 'ondown'))
          this[event.attrName] = new Function('event', event.newValue);
      ]]>
      </handler>
      <handler event="click">
      <![CDATA[
        var eventName = event.originalTarget.className;
        if (eventName != 'up' && eventName != 'down')
          return;

        var newEvent = document.createEvent('Events');
        newEvent.initEvent(eventName, false, true);
        this.dispatchEvent(newEvent);

        if (typeof this['on' + eventName] == 'function')
          this['on' + eventName].call(this, newEvent);
      ]]>
      </handler>
    </handlers>
  </binding>
</bindings>

Записываем это в spinbox.xml, к нему еще spinbox.css:

@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");

.up {
  list-style-image: url("spinbtn-up.gif")
}

.up:hover:active {
  list-style-image: url("spinbtn-up-act.gif")
}

.down {
  list-style-image: url("spinbtn-dn.gif")
}

.down:hover:active {
  list-style-image: url("spinbtn-dn-act.gif")
}

Картинки качаем из вышеупомянутого бага (или делаем сами, как больше нравится). В стилях приложения/расширения прописываем:

spinbox {
  -moz-binding: url(spinbox.xml#spinbox);
}

И теперь можем использовать новый элемент в своем XUL-файле:

<spinbox value="0" onup="this.value++" ondown="this.value--" />
спустя 18 дней [обр] Cube [досье]
Немного переделанный xbl, может, кому пригодится.
?xml version="1.0" encoding="UTF-8"?>

<bindings id="spinboxBindings"
          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="spinbox">
        <resources>
            <stylesheet src="data:text/css;charset=utf-8;base64,QG5hbWVzcGFjZSB1cmwoImh0dHA6Ly93d3cubW96aWxsYS5vcmcva2V5bWFzdGVyL2dhdGVrZWVwZXIvdGhlcmUuaXMub25seS54dWwiKTsNCi51cCB7IGxpc3Qtc3R5bGUtaW1hZ2U6IHVybCgiZGF0YTppbWFnZS9naWYsR0lGODlhJTBEJTAwJTBCJTAwJTkxJTAwJTAwaWltJUNGJUNGJUQxJTAwJTAwJTAwJUEwJUEwJUE0ISVGOSUwNCUwMCUwMCUwMCUwMCUwMCUyQyUwMCUwMCUwMCUwMCUwRCUwMCUwQiUwMCUwMCUwMiUyMiU4QyU4RiUyNjElRUQlMEYlRDYlOUIlMjMlQjInJUEwdCVBMiUzQiVDQnUlNUUlQjUlODklMjZ5USUwRCVBOCVBRSUxMiUwMCVDNyVGMmIlRDZiJTAxJTAwJTNCIik7IH0NCi51cFtkaXNhYmxlZD0idHJ1ZSJdIHsgbGlzdC1zdHlsZS1pbWFnZTogdXJsKCJkYXRhOmltYWdlL2dpZixHSUY4OWElMEQlMDAlMEIlMDAlQjMlMDAlMDBpaW0lQ0YlQ0YlRDElMDAlMDAlMDAlQTAlQTAlQTQlMDAlMDAlMDAlMDAlMDAlMDAlMDAlMDAlMDAlMDAlMDAlMDAlMDAlMDAlMDAlMDAlMDAlMDAlMDAlMDAlMDAlMDAlMDAlMDAlMDAlMDAlMDAlMDAlMDAlMDAlMDAlMDAlMDAlMDAlMDAlMDAlMkMlMDAlMDAlMDAlMDAlMEQlMDAlMEIlMDAlMDAlMDQlMUJQJUM4SSVFOSVCODglMEYlQTklM0IlQ0YlODIlRjYlNUQlMTMlMTglOTIlMTYlOEFWamclQkElMkYlQkNWdCUwNCUwMCUzQiIpOyB9DQoudXBbZGlzYWJsZWQ9InRydWUiXTpob3ZlcjphY3RpdmUgeyBsaXN0LXN0eWxlLWltYWdlOiB1cmwoImRhdGE6aW1hZ2UvZ2lmLEdJRjg5YSUwRCUwMCUwQiUwMCVCMyUwMCUwMGlpbSVDRiVDRiVEMSUwMCUwMCUwMCVBMCVBMCVBNCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUyQyUwMCUwMCUwMCUwMCUwRCUwMCUwQiUwMCUwMCUwNCUxQlAlQzhJJUU5JUI4OCUwRiVBOSUzQiVDRiU4MiVGNiU1RCUxMyUxOCU5MiUxNiU4QVZqZyVCQSUyRiVCQ1Z0JTA0JTAwJTNCIik7IH0NCi51cDpob3ZlcjphY3RpdmUgeyBsaXN0LXN0eWxlLWltYWdlOiB1cmwoImRhdGE6aW1hZ2UvZ2lmLEdJRjg5YSUwRCUwMCUwQiUwMCU5MSUwMCUwMCVGRiVGRiVGRmlpbSUwMCUwMCUwMCVBMCVBMCVBNCElRjklMDQlMDAlMDAlMDAlMDAlMDAlMkMlMDAlMDAlMDAlMDAlMEQlMDAlMEIlMDAlMDAlMDIhJTk0JThGJTE4JUNCJTFEJTE2JTg2JTlDJUYzJTg5OCUwMSVCNXglODBfQSVEMkdKJTlDRyU5NiclQjUlODlseDlOQiUxRiUwNSUwMCUzQiIpOyB9DQouZG93biB7IGxpc3Qtc3R5bGUtaW1hZ2U6IHVybCgiZGF0YTppbWFnZS9naWYsR0lGODlhJTBEJTAwJTBCJTAwJTkxJTAwJTAwaWltJUNGJUNGJUQxJTAwJTAwJTAwJUEwJUEwJUE0ISVGOSUwNCUwMCUwMCUwMCUwMCUwMCUyQyUwMCUwMCUwMCUwMCUwRCUwMCUwQiUwMCUwMCUwMiUyMyU4QyU4RiUyNjElRUQlMEYlRDYlOUIlMjMlQjIhJUIyJTE2VSVCNiVDRHUlRDclOTc5JUQ2JTE0NidleiVBQ1glMDElRjIlM0MlMkYlRTAtJTE0JTAwJTNCIik7IH0NCi5kb3duW2Rpc2FibGVkPSJ0cnVlIl0geyBsaXN0LXN0eWxlLWltYWdlOiB1cmwoImRhdGE6aW1hZ2UvZ2lmLEdJRjg5YSUwRCUwMCUwQiUwMCVCMyUwMCUwMGlpbSVDRiVDRiVEMSUwMCUwMCUwMCVBMCVBMCVBNCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUyQyUwMCUwMCUwMCUwMCUwRCUwMCUwQiUwMCUwMCUwNCUxQ1AlQzhJJUU5JUI4OCUwRiVBOSUzQiVERiU5NXAlN0QlRTAlODQlOTFlJTg2biVEQSVFQSU4OSU5RCUwQSVDN2NoRyUwMCUzQiIpOyB9DQouZG93bltkaXNhYmxlZD0idHJ1ZSJdOmhvdmVyOmFjdGl2ZSB7IGxpc3Qtc3R5bGUtaW1hZ2U6IHVybCgiZGF0YTppbWFnZS9naWYsR0lGODlhJTBEJTAwJTBCJTAwJUIzJTAwJTAwaWltJUNGJUNGJUQxJTAwJTAwJTAwJUEwJUEwJUE0JTAwJTAwJTAwJTAwJTAwJTAwJTAwJTAwJTAwJTAwJTAwJTAwJTAwJTAwJTAwJTAwJTAwJTAwJTAwJTAwJTAwJTAwJTAwJTAwJTAwJTAwJTAwJTAwJTAwJTAwJTAwJTAwJTAwJTAwJTAwJTAwJTJDJTAwJTAwJTAwJTAwJTBEJTAwJTBCJTAwJTAwJTA0JTFDUCVDOEklRTklQjg4JTBGJUE5JTNCJURGJTk1cCU3RCVFMCU4NCU5MWUlODZuJURBJUVBJTg5JTlEJTBBJUM3Y2hHJTAwJTNCIik7IH0NCi5kb3duOmhvdmVyOmFjdGl2ZSB7IGxpc3Qtc3R5bGUtaW1hZ2U6IHVybCgiZGF0YTppbWFnZS9naWYsR0lGODlhJTBEJTAwJTBCJTAwJTkxJTAwJTAwJUZGJUZGJUZGaWltJTAwJTAwJTAwJUEwJUEwJUE0ISVGOSUwNCUwMCUwMCUwMCUwMCUwMCUyQyUwMCUwMCUwMCUwMCUwRCUwMCUwQiUwMCUwMCUwMiElOTQlOEYlMTglQ0IlMUQlMTYlODYlOUMlRjMlODklMDglQjIlMDYlQzMlQzYlQjFxJTFENGklMTVZUiUxRSVDNSVBRSVFQ3k5TkIlMUYlMDUlMDAlM0IiKTsgfQ0KdGV4dGJveCB7IHBhZGRpbmc6IDBweDsgbWFyZ2luLXJpZ2h0OiAwcHg7IH0NCg%3D%3D"/>
        </resources>
    
        <content>
            <xul:hbox xbl:inherits="flex,width,disabled">
                <xul:textbox id="textField" flex="1"
                             xbl:inherits="type,value,maxlength,timeout,oninput,onchange,disabled"/>
                <xul:vbox pack="center">
                    <xul:image id="upButton" class="up" xbl:inherits="disabled"/>
                    <xul:image id="downButton" class="down" xbl:inherits="disabled"/>
                </xul:vbox>
            </xul:hbox>
        </content>
    
        <implementation>
            <constructor>
                <![CDATA[
                    if (this. getAttribute ("onup"))
                        this. setAttribute ("onup", this. getAttribute ("onup"));
                    if (this. getAttribute ("ondown"))
                        this. setAttribute ("ondown", this. getAttribute ("ondown"));
                ]]>
            </constructor>
            <property name="value"
                      onget="return document.getAnonymousElementByAttribute(this,'id','textField').value"
                      onset="document.getAnonymousElementByAttribute(this,'id','textField').value=val"/>
            <field name="pressed">false</field>
            <field name="_intervalID">false</field>
        </implementation>
    
        <handlers>
            <handler event="DOMAttrModified">
                <![CDATA[
                    if (event. target == this
                        && (event. attrName == "onup" || event. attrName == "ondown"))
                        this [event. attrName] = new Function ("event", event. newValue);
                ]]>
            </handler>
            
            <handler event="click">
                <![CDATA[
                    if (this. getAttribute ("disabled"))
                        return;
                    if (this. pressed)
                        clearInterval (this. _intervalID);
                    this. pressed = false;
                    var eventName = event. originalTarget. className;
                    if (eventName != "up" && eventName != "down")
                        return;
                    
                    var newEvent = document. createEvent ("Events");
                    newEvent. initEvent (eventName, false, true);
                    this. dispatchEvent (newEvent);
                    
                    if (typeof this ["on" + eventName] == "function")
                        this ["on" + eventName]. call (this, newEvent);
                ]]>
            </handler>
            
            <handler event="mousedown">
                <![CDATA[
                    if (this. getAttribute ("disabled"))
                        return;
                    var eventName = event. originalTarget. className;
                    if (eventName != "up" && eventName != "down")
                        return;
                    this. pressed = true;
                    
                    var newEvent = document. createEvent ("Events");
                    newEvent. initEvent (eventName, false, true);
                    this. dispatchEvent (newEvent);
                    
                    if (typeof this ["on" + eventName] == "function")
                    {
                        var x = this;
                        this. _intervalID = setInterval (function () { if (x. pressed) x ["on" + eventName]. call (x, newEvent); }, 250);
                    }
                ]]>
            </handler>
            
            <handler event="mouseup">
                <![CDATA[
                    if (this. pressed)
                        clearInterval (this. _intervalID);
                    this. pressed = false;
                    var eventName = event. originalTarget. className;
                    if (eventName != "up" && eventName != "down")
                        return;
                ]]>
            </handler>
            
            <handler event="mouseout">
                <![CDATA[
                    try
                    {
                        var eventName = event. originalTarget. className;
                    }
                    catch (e)
                    {
                        return;
                    }
                    if (eventName != "up" && eventName != "down")
                        return;
                    if (this. pressed)
                        clearInterval (this. _intervalID);
                    this. pressed = false;
                ]]>
            </handler>

        </handlers>

    </binding>

</bindings
Powered by POEM™ Engine Copyright © 2002-2005