Mozdev
mozilla/verbosio/core/content/bindings/regexp.xml
author Alex Vincent@SKYFIREDEMO1
Thu Aug 14 03:23:11 2008 -0700 (18 months ago)
changeset 9 31d8c997dbf0
permissions -rw-r--r--
Adding a Regular Expression Editor (Grid) binding.
     1 <?xml version="1.0"?>
     2 <!-- ***** BEGIN LICENSE BLOCK *****
     3    - Version: MPL 1.1/GPL 2.0/LGPL 2.1
     4    -
     5    - The contents of this file are subject to the Mozilla Public License Version
     6    - 1.1 (the "License"); you may not use this file except in compliance with
     7    - the License. You may obtain a copy of the License at
     8    - http://www.mozilla.org/MPL/
     9    -
    10    - Software distributed under the License is distributed on an "AS IS" basis,
    11    - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
    12    - for the specific language governing rights and limitations under the
    13    - License.
    14    -
    15    - The Original Code is XUL Menudeck Widget.
    16    -
    17    - The Initial Developer of the Original Code is
    18    - Alexander J. Vincent <ajvincent@gmail.com>.
    19    - Portions created by the Initial Developer are Copyright (C) 2004-2005
    20    - the Initial Developer. All Rights Reserved.
    21    -
    22    - Contributor(s):
    23    -
    24    - Alternatively, the contents of this file may be used under the terms of
    25    - either the GNU General Public License Version 2 or later (the "GPL"), or
    26    - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
    27    - in which case the provisions of the GPL or the LGPL are applicable instead
    28    - of those above. If you wish to allow use of your version of this file only
    29    - under the terms of either the GPL or the LGPL, and not to allow others to
    30    - use your version of this file under the terms of the MPL, indicate your
    31    - decision by deleting the provisions above and replace them with the notice
    32    - and other provisions required by the LGPL or the GPL. If you do not delete
    33    - the provisions above, a recipient may use your version of this file under
    34    - the terms of any one of the MPL, the GPL or the LGPL.
    35    -
    36    - ***** END LICENSE BLOCK ***** -->
    37 <!DOCTYPE bindings [
    38   <!ENTITY % namespaces.dtd SYSTEM "chrome://xulwidgets/content/namespaces.dtd">
    39   %namespaces.dtd;
    40 ]>
    41 <bindings xmlns="&XBL_NS;"
    42   xmlns:xbl="&XBL_NS;"
    43   xmlns:xul="&XUL_NS;"
    44   xmlns:html="&XHTML_NS;"
    45 >
    46   <binding id="regexp-cell">
    47     <implementation>
    48       <method name="getAnonElement">
    49         <parameter name="id"/>
    50         <body><![CDATA[
    51           return document.getAnonymousElementByAttribute(this, "anonid", id);
    52         ]]></body>
    53       </method>
    54 
    55       <property name="grid" readonly="true">
    56         <getter><![CDATA[
    57           var node = this;
    58           do {
    59             node = node.parentNode;
    60             if (!node)
    61               break;
    62           } while ((node.namespaceURI != this.namespaceURI) ||
    63                    (node.localName != "regexp-grid"));
    64           return node;
    65         ]]></getter>
    66       </property>
    67     </implementation>
    68   </binding>
    69 
    70   <binding id="regexp-column"
    71            extends="chrome://verbosio/content/bindings/regexp.xml#regexp-cell"
    72           >
    73     <content>
    74       <xul:vbox>
    75         <xul:textbox anonid="source"/>
    76         <xul:hbox anonclass="checkboxes">
    77           <xul:checkbox label="g" anonid="g"/>
    78           <xul:checkbox label="i" anonid="i"/>
    79           <xul:checkbox label="m" anonid="m"/>
    80         </xul:hbox>
    81         <xul:description anonid="result"/>
    82         <children/>
    83         <xul:button anonid="removeButton">Remove column</xul:button>
    84       </xul:vbox>
    85     </content>
    86     
    87     <implementation>
    88       <field name="source">
    89         this.getAnonElement("source");
    90       </field>
    91       <field name="g">
    92         this.getAnonElement("g");
    93       </field>
    94       <field name="i">
    95         this.getAnonElement("i");
    96       </field>
    97       <field name="m">
    98         this.getAnonElement("m");
    99       </field>
   100       <field name="result">
   101         this.getAnonElement("result");
   102       </field>
   103       <field name="removeButton">
   104         this.getAnonElement("removeButton");
   105       </field>
   106 
   107       <property name="flags" readonly="true">
   108         <getter><![CDATA[
   109           var rv = "";
   110           const flagsList = ["g", "i", "m"];
   111           for each (var item in flagsList)
   112           {
   113             if (this[item].checked)
   114               rv += item;
   115           }
   116           return rv;
   117         ]]></getter>
   118       </property>
   119 
   120       <field name="regexp">null</field>
   121 
   122       <method name="getRegExp">
   123         <body><![CDATA[
   124           try {
   125             return new RegExp(this.source.value, this.flags);
   126           } catch (e) {
   127             return null;
   128           }
   129         ]]></body>
   130       </method>
   131 
   132       <method name="update">
   133         <body><![CDATA[
   134           this.regexp = this.getRegExp();
   135           this.result.value = this.regexp ? this.regexp.toString() : "";
   136           this.grid.updateColumn(this);
   137         ]]></body>
   138       </method>
   139 
   140       <method name="initialize">
   141         <parameter name="source"/>
   142         <parameter name="flags"/>
   143         <body><![CDATA[
   144           this.source.value = source;
   145           this.flags.value = flags;
   146           this.update();
   147         ]]></body>
   148       </method>
   149 
   150       <constructor>
   151         var columnCell = this;
   152         this.removeButton.addEventListener("command", function(aEvt) {
   153           columnCell.grid.removeRegExp(columnCell);
   154           aEvt.stopPropagation();
   155           aEvt.preventDefault();
   156         }, false);
   157       </constructor>
   158     </implementation>
   159     
   160     <handlers>
   161       <handler event="command"><![CDATA[
   162         this.update();
   163       ]]></handler>
   164       <handler event="input"><![CDATA[
   165         this.update();
   166       ]]></handler>
   167     </handlers>
   168   </binding>
   169 
   170   <binding id="regexp-text"
   171            extends="chrome://verbosio/content/bindings/regexp.xml#regexp-cell"
   172           >
   173     <content>
   174       <xul:vbox>
   175         <xul:textbox multiline="true"
   176                      rows="3"
   177                      cols="20"
   178                      anonid="data"
   179                     />
   180         <xul:button anonid="delete-row">Delete row</xul:button>
   181       </xul:vbox>
   182     </content>
   183 
   184     <implementation>
   185       <method name="update">
   186         <body><![CDATA[
   187           this.grid.updateRow(this.parentNode);
   188         ]]></body>
   189       </method>
   190 
   191       <field name="deleteRow">
   192         this.getAnonElement("delete-row")
   193       </field>
   194 
   195       <field name="data">
   196         this.getAnonElement("data")
   197       </field>
   198 
   199       <constructor>
   200         var rowCell = this;
   201         this.deleteRow.addEventListener("command", function(aEvt) {
   202           rowCell.grid.removeTextRow(rowCell.parentNode);
   203           aEvt.stopPropagation();
   204           aEvt.preventDefault();
   205         }, false);
   206 
   207         this.data.addEventListener("input", function(aEvt) {
   208           rowCell.update();
   209         }, true);
   210       </constructor>
   211     </implementation>
   212   </binding>
   213 
   214 
   215   <binding id="regexp-exec"
   216            extends="chrome://verbosio/content/bindings/regexp.xml#regexp-cell"
   217           >
   218     <content>
   219       <html:pre anonid="data"/>
   220     </content>
   221     <implementation>
   222       <field name="data">
   223         this.getAnonElement("data");
   224       </field>
   225       <method name="setValue">
   226         <parameter name="value"/>
   227         <body><![CDATA[
   228           if (!this.data.firstChild)
   229           {
   230             var data = document.createCDATASection(value);
   231             this.data.appendChild(data);
   232             return;
   233           }
   234           this.data.firstChild.nodeValue = value;
   235         ]]></body>
   236       </method>
   237       <method name="exec">
   238         <parameter name="regexp"/>
   239         <parameter name="text"/>
   240         <body><![CDATA[
   241           if (!regexp || !text) {
   242             this.setValue("");
   243             return;
   244           }
   245 
   246           try {
   247             var results = regexp.exec(text);
   248           } catch (e) {
   249             this.setValue("");
   250             return;
   251           }
   252           if (!results) {
   253             this.setValue("");
   254             return;
   255           }
   256 
   257           var value = "";
   258           if (results instanceof Array)
   259           {
   260             for (var i = 0; i < results.length; i++)
   261               value += i + ": " + results[i] + "\n";
   262             value = value.substr(0, value.length - 1);
   263           } else
   264             value = results.toString();
   265           this.setValue(value);
   266         ]]></body>
   267       </method>
   268     </implementation>
   269   </binding>
   270 
   271   <binding id="regexp-grid">
   272     <!--
   273     Columns:
   274     * Text column
   275     * RegExp column
   276     * RegExp column
   277     * RegExp column
   278     * ...
   279       -->
   280     <content>
   281       <grid xmlns="&XUL_NS;" anonid="grid">
   282         <columns>
   283           <column/>
   284           <column/>
   285         </columns>
   286         <rows>
   287           <row anonid="regexp-row">
   288             <box/>
   289             <vbox><hbox>
   290               <button anonid="add-column">Add Column</button>
   291             </hbox></vbox>
   292           </row>
   293           <row anonid="last-row">
   294             <hbox>
   295               <button anonid="add-row">Add Row</button>
   296             </hbox>
   297           </row>
   298         </rows>
   299       </grid>
   300     </content>
   301 
   302     <implementation>
   303       <method name="getAnonElement">
   304         <parameter name="id"/>
   305         <body><![CDATA[
   306           return document.getAnonymousElementByAttribute(this, "anonid", id);
   307         ]]></body>
   308       </method>
   309       <field name="grid">
   310         this.getAnonElement("grid");
   311       </field>
   312 
   313       <field name="regexpRow">
   314         this.getAnonElement("regexp-row");
   315       </field>
   316 
   317       <field name="lastRow">
   318         this.getAnonElement("last-row");
   319       </field>
   320 
   321       <property name="columns" readonly="true">
   322         <getter><![CDATA[
   323           return this.regexpRow.getElementsByTagNameNS(
   324             this.namespaceURI,
   325             "regexp-column"
   326           );
   327         ]]></getter>
   328       </property>
   329 
   330       <property name="rows" readonly="true">
   331         <getter><![CDATA[
   332           var nodes = this.lastRow.parentNode.childNodes;
   333           var rv = [];
   334           for (var i = 1; i < nodes.length - 1; i++)
   335             rv.push(nodes[i]);
   336           return rv;
   337         ]]></getter>
   338       </property>
   339 
   340       <field name="gridCells">([/* (columns, rows) */])</field>
   341 
   342       <method name="getGridCell">
   343         <parameter name="columnIndex"/>
   344         <parameter name="rowIndex"/>
   345         <body><![CDATA[
   346           while (columnIndex >= this.columns.length)
   347             this.addRegExp(null, null);
   348 
   349           while (columnIndex >= this.gridCells.length)
   350             this.gridCells.push([]);
   351 
   352           var gridColumn = this.gridCells[columnIndex];
   353 
   354           while (rowIndex >= this.rows.length)
   355             this.addTextRow("");
   356 
   357           while (rowIndex >= gridColumn.length) {
   358             var cell = document.createElementNS(this.namespaceURI, "regexp-exec");
   359             var insertIndex = gridColumn.length;
   360             this.rows[insertIndex].appendChild(cell);
   361             gridColumn.push(cell);
   362           }
   363 
   364           return gridColumn[rowIndex];
   365         ]]></body>
   366       </method>
   367 
   368       <method name="removeGridCell">
   369         <parameter name="columnIndex"/>
   370         <parameter name="rowIndex"/>
   371         <body><![CDATA[
   372           var gridColumn = this.gridCells[columnIndex];
   373           var gridCell = gridColumn[rowIndex];
   374           gridColumn.splice(rowIndex, 1);
   375           gridCell.parentNode.removeChild(gridCell);
   376         ]]></body>
   377       </method>
   378 
   379       <method name="updateCell">
   380         <parameter name="columnIndex"/>
   381         <parameter name="rowIndex"/>
   382         <body><![CDATA[
   383           var cell = this.getGridCell(columnIndex, rowIndex);
   384           var node = this.rows[rowIndex];
   385           node = node.getElementsByTagNameNS(this.namespaceURI, "regexp-text")[0];
   386 
   387           var text = node.data.value;
   388           var regexp = this.columns[columnIndex].regexp;
   389           cell.exec(regexp, text);
   390         ]]></body>
   391       </method>
   392 
   393       <method name="updateColumn">
   394         <parameter name="columnCell"/>
   395         <body><![CDATA[
   396           var columns = this.columns;
   397           for (var i = 0; i < columns.length; i++)
   398           {
   399             if (columns[i] != columnCell)
   400               continue;
   401             var rows = this.rows;
   402             for (var j = 0; j < rows.length; j++)
   403               this.updateCell(i, j);
   404             break;
   405           }
   406         ]]></body>
   407       </method>
   408 
   409       <method name="updateRow">
   410         <parameter name="rowElement"/>
   411         <body><![CDATA[
   412           var rows = this.rows;
   413           for (var i = 0; i < rows.length; i++)
   414           {
   415             if (rows[i] != rowElement)
   416               continue;
   417             var columns = this.columns;
   418             for (var j = 0; j < columns.length; j++)
   419               this.updateCell(j, i);
   420             break;
   421           }
   422         ]]></body>
   423       </method>
   424 
   425       <method name="addRegExp">
   426         <parameter name="regexpSrc"/>
   427         <parameter name="regexpFlags"/>
   428         <parameter name="childFragment"/>
   429         <body><![CDATA[
   430           var columnCell = document.createElementNS(this.namespaceURI,
   431                                                     "regexp-column");
   432           if (childFragment instanceof Components.interfaces.nsIDOMDocumentFragment)
   433             columnCell.appendChild(childFragment.cloneNode(true));
   434 
   435           this.regexpRow.insertBefore(columnCell, this.regexpRow.lastChild);
   436           columnCell.initialize(regexpSrc, regexpFlags);
   437           
   438           this.updateColumn(columnCell);
   439         ]]></body>
   440       </method>
   441 
   442       <method name="addTextRow">
   443         <parameter name="value"/>
   444         <body><![CDATA[
   445           var newRow = document.createElementNS(this.namespaceURI, "xul:row");
   446           var text = document.createElementNS(this.namespaceURI, "xul:regexp-text");
   447           newRow.appendChild(text);
   448           this.lastRow.parentNode.insertBefore(newRow, this.lastRow);
   449           if (value)
   450             text.value = value;
   451           this.updateRow(newRow);
   452         ]]></body>
   453       </method>
   454 
   455       <method name="removeRegExp">
   456         <parameter name="columnElement"/>
   457         <body><![CDATA[
   458           var columns = this.columns;
   459           for (var i = 0; i < columns.length; i++) {
   460             if (columns[i] != columnElement)
   461               continue;
   462 
   463             var rows = this.rows;
   464             for (var j = 0; j < rows.length; j++)
   465               this.removeGridCell(i, j);
   466             columnElement.parentNode.removeChild(columnElement);
   467             break;
   468           }
   469         ]]></body>
   470       </method>
   471 
   472       <method name="removeTextRow">
   473         <parameter name="rowElement"/>
   474         <body><![CDATA[
   475           var rows = this.rows;
   476           for (var i = 0; i < rows.length; i++)
   477           {
   478             if (rows[i] != rowElement)
   479               continue;
   480 
   481             var columns = this.columns;
   482             for (var j = 0; j < columns.length; j++)
   483               this.removeGridCell(j, i);
   484             rowElement.parentNode.removeChild(rowElement);
   485             break;
   486           }
   487         ]]></body>
   488       </method>
   489 
   490 
   491       <field name="addRowButton">
   492         this.getAnonElement("add-row");
   493       </field>
   494 
   495       <field name="addColumnButton">
   496         this.getAnonElement("add-column");
   497       </field>
   498 
   499       <constructor><![CDATA[
   500         var grid = this;
   501 
   502         this.addRowButton.addEventListener("command", function() {
   503           grid.addTextRow("");
   504         }, true);
   505 
   506         this.addColumnButton.addEventListener("command", function() {
   507           grid.addRegExp(null, null);
   508         }, true);
   509       ]]></constructor>
   510     </implementation>
   511   </binding>
   512 </bindings>