Captain's Universe Home
Captain's Universe Home
Cosmic Ray Muon DetectorTeleGarden Pages
Time on MarsBryophyllum Plants
Jupiter Radio AstronomyAncient Pages
Salzburg Tourist GuideEarth Magnetometer
  H O M E     AJAX & MORE     LINUX & MORE     RTAI     XENOMAI     ADEOS IPIPE      
    JAVA & BROWSERS     *NIX     ELECTRONICS     REVIEWS     ARTEMIA     FAIRY SHRIMP      


XUL tree - Adding nodes with a context menu / edit node names example/tutorial

The XUL language is very powerful. Powerful enough to forget traditional means of doing web applications with HTML and using the many widget available with XUL.


There are many Javascript-Tree implementations out there, but all are either not cross-browser compliant or are slow etc. Not so with native XUL trees. This example shows how to add nodes by right-clicking on a node or item and selecting the context-menu "Add node". A prompt shows up where you can enter the name, and after clicking on OK, the node is added. Furthermore the name of the node can be edited by double-clicking on the node. In combination with AJAX this is a very powerful tool:
AJAX/Javascript Form GET Request
AJAX/Javascript Form POST Request
AJAX/Javascript XML Processing Example/Tutorial

UPDATE: There is another implementation of the same available at: XUL Tree Edit/Add NEW Tutorial


tree.xul
<?xml version="1.0"?>

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


<window id="treeImage" title="Tree With Images"
        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script>
<![CDATA[
var currentid;
var currentobj;

function addnode() {
   var ti = currentobj.parentNode.parentNode;
   mylabel = prompt("Name of node:", "name");
   if(!mylabel) {    return; }

   if (ti.getAttribute("container") != "true") {
      ti.setAttribute("container","true");
      ti.setAttribute("open","true");
   }
   var i = 0;
   var foundchild = 0;
   for (i=0; i < ti.childNodes.length; i++) {
      if (ti.childNodes[i].nodeName == "treechildren") {
         var ti = ti.childNodes[i];
         var titem = document.createElement("treeitem");
         var trow = document.createElement("treerow");
         var tcell = document.createElement("treecell");
         tcell.setAttribute("label", mylabel);
         trow.appendChild(tcell);
         titem.appendChild(trow);
         ti.appendChild(titem);
         foundchild = 1;
         
      }
   }
   if (foundchild == 0) {
      var ti = currentobj.parentNode.parentNode;
      var tch = document.createElement("treechildren");
      var titem = document.createElement("treeitem");
      var trow = document.createElement("treerow");
      var tcell = document.createElement("treecell");
      tcell.setAttribute("label", mylabel);
      trow.appendChild(tcell);
      titem.appendChild(trow);
      tch.appendChild(titem);
      ti.appendChild(tch);
   }

}
]]>
</script>

<popupset label="zzzo">
  <popup id="clipmenu" >
    <menuitem label="Add Node" oncommand="addnode();"/>
  </popup>
</popupset>

<tree id="thetree" flex="1" width="350" height="200" >
  <treecols>
    <treecol id="name" label="Name" primary="true" flex="1"/>
  </treecols>

<treechildren>
<treeitem container="true" open="true">
   <treerow>
      <treecell label="1111"/>
   </treerow>
      <treechildren>
         <treeitem container="true" open="true">
            <treerow>
               <treecell label="2222"/>
            </treerow>
         </treeitem>
         <treeitem container="true" open="true">
            <treerow>
               <treecell label="3333"/>
            </treerow>
            <treechildren id="child">
               <treeitem container="true" open="true">
                  <treerow>
                     <treecell label="4444"/>
                  </treerow>                     
               </treeitem>
               <treeitem container="true" open="true">
                  <treerow>
                     <treecell label="5555"/>
                  </treerow>                     
               </treeitem>
            </treechildren>
         </treeitem>
      </treechildren>
   </treeitem>
   <treeitem container="true" open="true">
      <treerow>
         <treecell label="6666"/>
      </treerow>
      <treechildren>
         <treeitem container="true" open="true">
            <treerow>
               <treecell label="7777"/>
            </treerow>
         </treeitem>
      </treechildren>
   </treeitem>
</treechildren>
</tree>

</window>



edittree.css
tree
{
  -moz-binding: url("edittree.xml#edittree");
  -moz-user-focus: normal !important;
  -moz-user-select: text;
}

textbox {
  min-height: 1.8em;
  -moz-user-focus: normal !important;
  -moz-user-select: text !important;
}

tree[editing] > treechildren:-moz-tree-row(selected)
{
  background-color: transparent;
  border: none;
}

edittree.xml
Based on the example posted at xulplanet.com
<?xml version="1.0"?>

<bindings id="treeEditBindings"
   xmlns="http://www.mozilla.org/xbl"
   xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">

  <binding id="edittree" extends="chrome://global/content/bindings/tree.xml#tree">
    <content>
      <children includes="treecols"/>
      <xul:stack flex="1">
        <xul:treerows class="tree-rows" flex="1">
          <children/>
        </xul:treerows>
        <xul:textbox ileattr="text" left="0" top="0" hidden="true"/>
      </xul:stack>
    </content>
    <implementation>
      <field name="_editOriginalValue">0</field>
      <field name="_editRow">-1</field>
      <field name="_editCol">null</field>
      <field name="onAccept">null</field>
      <method name="setEditMode">
        <parameter name="x"/>
        <parameter name="y"/>
        <parameter name="val"/>
        <body>
        <![CDATA[
          var txt = document.getAnonymousElementByAttribute(this, "ileattr", "text");
          if (val){
            if (x < 0) return;

            var originalValue = this.view.getCellText(x,y);
            var cellnode = this.getCellNodeAt(x,y);
            if (!(cellnode || this.view.isEditable(x,y))) return;

            if (this._editRow >= 0) this._assignValueToCell(txt.value,true);

            if (cellnode && cellnode.getAttribute("readonly")) return;
            txt.removeAttribute("hidden");

            var treeBox = this.treeBoxObject;
            var outx = {}, outy = {}, outwidth = {}, outheight = {};
            var coords = treeBox.getCoordsForCellItem(x,y,"text",outx,outy,outwidth,outheight);

            this._editRow = x;
            this._editCol = y;

            txt.setAttribute("left",outx.value-3);
            txt.setAttribute("top",outy.value-3);
            txt.setAttribute("height",outheight.value);

            var coords = treeBox.getCoordsForCellItem(x,y,"cell",outx,outy,outwidth,outheight);
            txt.setAttribute("width",outwidth.value - outy.value);

            this._editOriginalValue = originalValue;
            if (cellnode) cellnode.setAttribute("label","");
            this.view.setCellText(x,y,"");

            txt.value = originalValue;
            txt.select();
            this.setAttribute("editing","true");

            txt.addEventListener("keydown", this.fieldKeyDown, false);
            txt.addEventListener("blur", this.fieldChange, true);
          }
          else {
            this.removeAttribute("editing");

            txt.setAttribute("hidden","true");
            txt.removeEventListener("keydown", this.fieldKeyDown, false);
            txt.removeEventListener("blur", this.fieldChange, true);
            txt.blur();
          }
        ]]>
        </body>
      </method>
      <method name="getCellNodeAt">
        <parameter name="row"/>
        <parameter name="col"/>
        <body>
          var view;
          try {
            view = this.contentView;
          } catch (ex){}
          if (view){
            var elem = view.getItemAtIndex(row);
            if (elem){
              var pos = ((document.getElementById(col).ordinal - 1) >> 1);
              return elem.firstChild.childNodes[pos];
            }
          }
          return null;
        </body>
      </method>
      <method name="fieldKeyDown">
        <parameter name="aEvent"/>
        <body>
        <![CDATA[
          var tree = aEvent.target;
          while (tree && tree.tagName != "tree") tree = tree.parentNode;
          if (aEvent.keyCode == 13){
            tree._assignValueToCell(this.value,true);
          }
          if (aEvent.keyCode == 27){
            tree._assignValueToCell(tree._editOriginalValue,false);
          }
          aEvent.preventBubble();
        ]]>
        </body>
      </method>
      <method name="_assignValueToCell">
        <parameter name="value"/>
        <parameter name="acceptMode"/>
        <body>
        <![CDATA[
          if (this._editRow == -1) return;
          if (acceptMode && this.onAccept &&
              this.onAccept(this._editRow,this._editCol,this._editOriginalValue,value))
            return;

          var cellnode = this.getCellNodeAt(this._editRow,this._editCol);
          if (cellnode) cellnode.setAttribute("label",value);
          this.view.setCellText(this._editRow,this._editCol,value);
          this.treeBoxObject.invalidateCell(this._editRow,this._editCol);
          this._editRow = -1;
          this._editCol = null;

          this.setEditMode("normal");
        ]]>
        </body>
      </method>
      <method name="fieldChange">
        <parameter name="aEvent"/>
        <body>
        <![CDATA[
          var tree = aEvent.target;
          while (tree && tree.tagName != "tree") tree = tree.parentNode;
          tree._assignValueToCell(this.value,true);
        ]]>
        </body>
      </method>
    </implementation>
    <handlers>
      <handler event="dblclick">
        var treeBox = this.treeBoxObject;
        var row = {};
        var col = {};
        var obj = {};
        treeBox.getCellAt(event.clientX,event.clientY,row,col,obj);
        this.setEditMode(row.value,col.value,true);
      </handler>
      <handler event="click" button="2">
        var treeBox = this.treeBoxObject;
        var row = {};
        var col = {};
        var obj = {};
        treeBox.getCellAt(event.clientX,event.clientY,row,col,obj);
        var cellnode = this.getCellNodeAt(row.value,col.value);
        currentid = cellnode.id;
        currentobj = cellnode;
        document.getElementById('clipmenu').showPopup(
                     document.documentElement, event.clientX,
                     event.clientY, "bottomleft", "topleft");
      </handler>
    </handlers>
  </binding>
</bindings>


Last-Modified: Sat, 04 Feb 2006 16:02:58 GMT

Google
 
Web www.captain.at
go to top
© 1996-2010 . All rights reserved.
No reproduction, distribution, publishing or transmission of the copyrighted materials at this site is permitted. Policy
go to top