You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@lucene.apache.org by ke...@apache.org on 2004/05/17 15:04:43 UTC

cvs commit: jakarta-lucene-sandbox/contributions/javascript/queryConstructor testQueryConstructor.html luceneQueryConstructor.js luceneQueryConstructor.html

kelvint     2004/05/17 06:04:43

  Modified:    contributions/javascript/queryConstructor
                        luceneQueryConstructor.js
                        luceneQueryConstructor.html
  Added:       contributions/javascript/queryConstructor
                        testQueryConstructor.html
  Log:
  Complete revamp of luceneQueryConstructor.
  Added demo and introduction HTML page.
  Added jsUnit tests.
  
  WARNING: this version should be considered incompatible with previous versions.
  Migration effort is minimal and I'm happy to answer questions about migration posted to lucene-user, but
  I'm under the impression the previous versions weren't widely used (if at all) anyways.
  
  Revision  Changes    Path
  1.9       +143 -76   jakarta-lucene-sandbox/contributions/javascript/queryConstructor/luceneQueryConstructor.js
  
  Index: luceneQueryConstructor.js
  ===================================================================
  RCS file: /home/cvs/jakarta-lucene-sandbox/contributions/javascript/queryConstructor/luceneQueryConstructor.js,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- luceneQueryConstructor.js	6 Mar 2004 08:22:05 -0000	1.8
  +++ luceneQueryConstructor.js	17 May 2004 13:04:42 -0000	1.9
  @@ -3,14 +3,21 @@
   // Version: $Id$
   
   // Change this according to what you use to name the field modifiers in your form.
  -// e.g. with the field "name", the modifier will be called "nameModifier"
  +// e.g. with the search field "name", the form element of its modifier 
  +// will be "name<modifierSuffix>"
   var modifierSuffix = 'Modifier';
   
  +// If not a field-specific search
  +// e.g. with the arbitary form element 'foobar', its modifier will be 
  +// <noFieldPrefix>foobarModifier and its form element 
  +// will be <noFieldPrefix>foobar
  +var noFieldPrefix = 'noField-';
  +
   // Do you wish the query to be displayed as an alert box?
   var debug = false;
   
   // Do you wish the function to submit the form upon query construction?
  -var submitOnConstruction = false;
  +var submitForm = false;
   
   // prefix modifier for boolean AND queries
   var AND_MODIFIER = '+';
  @@ -19,10 +26,15 @@
   var NOT_MODIFIER = '-';
   
   // prefix modifier for boolean OR queries
  -var OR_MODIFIER  = '';
  +var OR_MODIFIER  = ' ';
  +
  +var NO_MODIFIER = 0;
  +
  +// default modifier for terms
  +var DEFAULT_TERM_MODIFIER = AND_MODIFIER;
   
  -// default prefix modifier for boolean queries
  -var DEFAULT_MODIFIER = OR_MODIFIER;
  +// default modifier for groups of terms (denoted by parantheses)
  +var DEFAULT_GROUP_MODIFIER = AND_MODIFIER;
   
   // used to delimit multiple values from checkboxes and select lists
   var VALUE_DELIMITER = ' ';
  @@ -30,19 +42,18 @@
   // Constructs the query
   // @param query Form field to represent the constructed query to be submitted
   // @param debug Turn on debugging?
  -// @return Submits the form if submitOnConstruction=true, else returns the query param
   function doMakeQuery( query, dbg )
   {
     if(typeof(dbg) != "undefined")
       debug = dbg;
  -
  +    
     var frm = query.form;
     var formElements = frm.elements;
     query.value = '';
  -
  +  
     // keep track of the fields we've examined
     var dict = new Array();
  -
  +  
     for(var i=0; i<formElements.length; i++)
     {
       var element = formElements[i];
  @@ -50,45 +61,40 @@
       if(elementName != "" && !contains(dict, elementName))
       {
         dict[dict.length] = elementName;
  -
  +      
         // ensure we get the whole group (of checkboxes, radio, etc), if applicable
  -      var elementValue = trim(getFieldValue(frm[element.name]));
  -
  -      if(elementValue.length > 0 && elementValue != ' ')
  +      var elementValue = getFieldValue(frm[element.name]);
  +      if(elementValue.length > 0)
         {
           var subElement = frm[elementName + modifierSuffix];
           if(typeof(subElement) != "undefined") // found a field/fieldModifier pair
           {
  -          // assume that the user only allows one logic, i.e. AND OR, AND NOT, OR NOT, etc not supported
  -          var logic = getFieldValue(subElement);
  -
  -          if(logic == 'And')
  -          {
  -            addFieldWithModifier(query, AND_MODIFIER, elementName, elementValue);
  -          }
  -          else if(logic == 'Not')
  -          {
  -            addFieldWithModifier(query, NOT_MODIFIER, elementName, elementValue);
  -          }
  -          else if(logic == 'Or')
  +          var termMod, groupMod;
  +          var modifier = getFieldValue(subElement);
  +          // modifier field is in the form <termModifier>|<groupModifier>
  +          if(modifier.indexOf('|') > -1)
             {
  -            addFieldWithModifier(query, OR_MODIFIER, elementName, elementValue);
  +            var idx = modifier.indexOf('|');
  +            termMod = modifier.substring(0, idx);
  +            if(termMod == '') termMod = DEFAULT_TERM_MODIFIER;
  +            groupMod = modifier.substring(idx + 1);
  +            if(groupMod == '') groupMod = DEFAULT_GROUP_MODIFIER;
             }
             else
             {
  -            addFieldWithModifier(query, DEFAULT_MODIFIER, elementName, elementValue);
  +            termMod = modifier;
  +            if(termMod == '') termMod = DEFAULT_TERM_MODIFIER;
  +            groupMod = DEFAULT_GROUP_MODIFIER;
             }
  +          appendTerms(query, termMod, elementValue, elementName, groupMod);
           }
         }
       }
     }
   
  -  if(debug)
  -  {
  -    alert('Query:' + query.value);
  -  }
  -
  -  if(submitOnConstruction)
  +  if(debug) {alert('Query:' + query.value);}
  +  
  +  if(submitForm)
     {
       frm.submit();
     }
  @@ -103,14 +109,8 @@
   // @return Submits the form if submitOnConstruction=true, else returns the query param
   function doANDTerms(query)
   {
  -  var temp = '';
  -  splitStr = query.value.split(" ");
  -  query.value = '';
  -  for(var i=0;i<splitStr.length;i++)
  -  {
  -    if(splitStr[i].length > 0) addModifier(query, AND_MODIFIER, splitStr[i]);
  -  }
  -  if(submitOnConstruction)
  +  appendTerms(query, AND_MODIFIER, query.value);
  +  if(submitForm)
     {
       frm.submit();
     }
  @@ -120,26 +120,103 @@
     }
   }
   
  -function contains(array, s)
  +function buildTerms(termModifier, fieldValue)
   {
  -  for(var i=0; i<array.length; i++)
  +  fieldValue = trim(fieldValue);
  +  var splitStr = fieldValue.split(" ");
  +  fieldValue = '';
  +  var inQuotes = false;
  +  for(var i=0;i<splitStr.length;i++)
     {
  -    if(s == array[i])
  -      return true;
  +    if(splitStr[i].length > 0)
  +    {
  +      if(!inQuotes)
  +      {
  +        fieldValue = fieldValue + termModifier + splitStr[i] + ' ';
  +      }
  +      else
  +      { 
  +        fieldValue = fieldValue + splitStr[i] + ' ';
  +      }      
  +      if(splitStr[i].indexOf('"') > -1) inQuotes = !inQuotes
  +    }
     }
  -  return false;
  +  fieldValue = trim(fieldValue);  
  +  return fieldValue;
   }
   
  +// Appends terms to a query. 
  +// @param query Form field of query
  +// @param termModifier Term modifier
  +// @param value Value to be appended. Tokenized by spaces, 
  +//    and termModifier will be applied to each token.
  +// @param fieldName Name of search field. Omit if not a field-specific query.
  +// @param groupModifier Modifier applied to each group of terms.
  +// @return query form field
  +function appendTerms(query, termModifier, value, fieldName, groupModifier)
  +{
  +  if(typeof(groupModifier) == "undefined")
  +    groupModifier = DEFAULT_GROUP_MODIFIER;
  +  
  +  value = buildTerms(termModifier, value);
  +  
  +  // not a field-specific search
  +  if(fieldName == null || fieldName.indexOf(noFieldPrefix) != -1 || fieldName.length == 0)
  +  {
  +    if(groupModifier == NO_MODIFIER)
  +    {
  +      if(query.value.length == 0)
  +      {
  +        query.value = value;
  +      }
  +      else
  +      {
  +        query.value = query.value + ' ' + value;
  +      }  
  +    }
  +    else
  +    { 
  +      if(query.value.length == 0)
  +      {
  +        query.value = groupModifier + '(' + value + ')';
  +      }
  +      else
  +      {
  +        query.value = query.value + ' ' + groupModifier + '(' + value + ')';
  +      }  
  +    }
  +  }
  +  else
  +  {
  +    if(query.value.length == 0)
  +    {
  +      query.value = groupModifier + fieldName + ':(' + value + ')';
  +    }
  +    else
  +    {
  +      query.value = query.value + ' ' + groupModifier +fieldName + ':(' + value + ')';
  +    }  
  +  }
  +  query.value = trim(query.value)
  +  return query;
  +}
  +
  +// Obtain the value of a form field.
  +// @param field Form field
  +// @return Array of values, or string value depending on field type, 
  +//    or empty string if field param is undefined or null
   function getFieldValue(field)
   {
  -  if(typeof(field[0]) != "undefined" && field[0].type=="checkbox")
  +  if(field == null || typeof(field) == "undefined")
  +    return "";
  +  if(typeof(field) != "undefined" && typeof(field[0]) != "undefined" && field[0].type=="checkbox")
       return getCheckedValues(field);
  -  if(typeof(field[0]) != "undefined" && field[0].type=="radio")
  +  if(typeof(field) != "undefined" && typeof(field[0]) != "undefined" && field[0].type=="radio")
       return getRadioValue(field);
  -  if(field.type.match("select*"))
  +  if(typeof(field) != "undefined" && field.type.match("select*")) 
       return getSelectedValues(field);
  -
  -  return field.value;
  +  if(typeof(field) != "undefined")
  +    return field.value;
   }
   
   function getRadioValue(radio)
  @@ -172,45 +249,35 @@
     return r.join(VALUE_DELIMITER);
   }
   
  -function addModifier(query, modifier, value)
  +function quote(value)
   {
  -  value = trim(value);
  -  
  -  if(query.value.length == 0)
  -  {
  -    query.value = modifier + '(' + value + ')';
  -  }
  -  else
  -  {
  -    query.value = query.value + ' ' + modifier + '(' + value + ')';
  -  }  
  +  return "\"" + trim(value) + "\"";
   }
   
  -function addFieldWithModifier(query, modifier, field, fieldValue)
  +function contains(array, s)
   {
  -  fieldValue = trim(fieldValue);
  -
  -  if(query.value.length == 0)
  -  {
  -    query.value = modifier + '(' + field + ':(' + fieldValue + '))';
  -  }
  -  else
  +  for(var i=0; i<array.length; i++)
     {
  -    query.value = query.value + ' ' + modifier + '(' + field + ':(' + fieldValue + '))';
  +    if(s == array[i])
  +      return true;
     }
  +  return false;
   }
   
   function trim(inputString) {
      if (typeof inputString != "string") { return inputString; }
  -
  +   
      var temp = inputString;
  -
  +   
      // Replace whitespace with a single space
      var pattern = /\s+/ig;
      temp = temp.replace(pattern, " ");
  -
  -   // Trim
  +  
  +   // Trim 
      pattern = /^(\s*)([\w\W]*)(\b\s*$)/;
      if (pattern.test(temp)) { temp = temp.replace(pattern, "$2"); }
  +   // run it another time through for words which don't end with a character or a digit
  +   pattern = /^(\s*)([\w\W]*)(\s*$)/;
  +   if (pattern.test(temp)) { temp = temp.replace(pattern, "$2"); }
      return temp; // Return the trimmed string back to the user
  -}
  +}
  \ No newline at end of file
  
  
  
  1.3       +175 -58   jakarta-lucene-sandbox/contributions/javascript/queryConstructor/luceneQueryConstructor.html
  
  Index: luceneQueryConstructor.html
  ===================================================================
  RCS file: /home/cvs/jakarta-lucene-sandbox/contributions/javascript/queryConstructor/luceneQueryConstructor.html,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- luceneQueryConstructor.html	23 Jan 2004 16:59:38 -0000	1.2
  +++ luceneQueryConstructor.html	17 May 2004 13:04:42 -0000	1.3
  @@ -1,68 +1,185 @@
   <html>
     <head>
  -    <title>Demo Lucene Query Constructor</title>
  +    <meta name="Author" content="Kelvin Tan">
  +    <title>Lucene Query Constructor Demo and Introduction</title>
       <script type="text/javascript" src="luceneQueryConstructor.js"></script>
  -    <script type="text/javascript" src="../queryValidator/luceneQueryValidator.js"></script>
  +    <script>
  +      function submitForm(frm)
  +      {
  +        if(frm["noField-phrase-input"].value.length > 0)
  +          frm["noField-phrase"].value = quote(frm["noField-phrase-input"].value)
  +        else if(frm["noField-phrase"].value.length > 0)
  +          frm["noField-phrase"].value = ''
  +        doMakeQuery(frm.query,true);
  +      }
  +    </script>
     </head>
  -
  +  
     <body>
  +  <h2>Lucene Javascript Query Constructor</h2>
  +  <p>luceneQueryConstructor.js is a Javascript framework for constructing queries using the "advanced" search features of lucene, 
  +  namely field-searching, boolean searching, phrase searching, group searching (via parentheses) and various combinations of the aforementioned.
  +  <p>It also provides a convenient way to mimic a Google-like search, where all terms are ANDed, as opposed to Lucene's default OR modifier.
  +  <p>
  +  This HTML form provides examples on the usage of luceneQueryConstructor.js. 
  +  An interface similar to <a href="http://www.google.com/advanced_search">Google's Advanced Search</a> form is shown here.
       <form>
  -      <p>
  +  <table width="100%" border="0" cellspacing="1" cellpadding="5"> 
  +    <tr>
  +      <th></th>
  +      <td width="25%"></td>    
  +      <tr>
  +        <th>
  +          <input name="noField-andModifier" value="+|0" type="hidden"><b>Find results</b>
  +        </th>
  +        <td class="bodytext">With <b>all</b> of the words</td>
  +        <td class="bodytext">
  +          <input type="text" name="noField-and" size="25">
  +          <select name="resultsPerPage">
  +          <option value="10">10 results<option value="20">20 results
  +          <option value="50" selected>50 results</select>    
  +        </td>
  +      </tr>
  +      <tr>
  +        <th>
  +          <input name="noField-phraseModifier" value="+|+" type="hidden">
  +        </th>
  +        <td class="bodytext">With the <b>exact phrase</b></td>
  +        <td class="bodytext">
  +        <input type="text" name="noField-phrase-input" size="25">
  +        <input type="hidden" name="noField-phrase">
  +        </td>
  +      </tr>
  +      <tr>
  +        <th>
  +          <input name="noField-orModifier" value=" |+" type="hidden">
  +        </th>
  +        <td class="bodytext">With <b>at least</b> one of the words</td>
  +        <td class="bodytext">
  +          <input type="text" name="noField-or" size="25">
  +        </td>
  +      </tr>
  +      <tr>
  +        <th>
  +          <input name="noField-notModifier" value="-|0" type="hidden">
  +        </th>
  +        <td class="bodytext"><b>Without</b> the words</td>
  +        <td class="bodytext">
  +          <input type="text" name="noField-not" size="25">
  +        </td>
  +      </tr>
  +      <tr>
  +        <th>
  +          <b>File Format</b>
  +        </th>
  +        <td class="bodytext">
  +        <select name="fileNameModifier"><option value="And" selected>Only</option><option value="Not">Don't</option></select>
  +        return results of the file format</td>
  +        <td class="bodytext">
  +          <select name="fileName"><option value="" selected>any format<option value="pdf">Adobe Acrobat PDF (.pdf)
  +          <option value="doc">Microsoft Word (.doc)<option value="xls">Microsoft Excel (.xls)<option value="ppt">Microsoft Powerpoint (.ppt)</select>
  +        </td>
  +      </tr>
  +      <tr>
  +        <th>
  +          <b>Date</b>
  +        </th>
  +        <td class="bodytext">
  +        Return results updated in the </td>
  +        <td class="bodytext">
  +          <select name="date"><option value="" selected>anytime<option value="3">past 3 months
  +          <option value="6">past 6 months<option value="12">past year</select>
  +          <input type="hidden" name="fromDate">
  +          <input type="hidden" name="toDate">
  +          <input type="hidden" name="dateRangeField" value="lastModifiedDate">    
  +        </td>
  +      </tr>
         <input type="hidden" name="query">
  -      Name:
  -      <input type="text" name="name">
  -      <select name="nameModifier">
  -        <option value="And">And</option>
  -        <option value="Or" selected="selected">Or</option>
  -        <option value="Not">Not</option>
  -      </select>
  -      </p>
  -
  -      <p>
  -      Description:
  -      <input type="text" name="description">
  -      <select name="descriptionModifier">
  -        <option value="And">And</option>
  -        <option value="Or" selected="selected">Or</option>
  -        <option value="Not">Not</option>
  -      </select>
  -      </p>
  -
  -      <p>
  -      Required Select:
  -      <select name="choice">
  -        <option value="one">One</option>
  -        <option value="two">Two</option>
  -      </select>
  -      <input type="hidden" name="choiceModifier" value="And"/>
  -      </p>
  -
  -      <p>
  -      Multi-select:
  -      <select name="multi" multiple="true" size="5">
  -        <option value="multi1">multi1</option>
  -        <option value="multi2">multi2</option>
  -        <option value="multi3">multi3</option>
  -        <option value="multi4">multi4</option>
  -      </select>
  -      <input type="hidden" name="multiModifier" value="Or"/>
  -      </p>
  -
  -      <p>
  -      Radio:
  -      <!-- TODO: something fishy happens if none selected -->
  -      <input type="radio" name="radio" value="wnrn" checked="checked" />WNRN
  -      <input type="radio" name="radio" value="klpx" />KLPX
  -      <input type="hidden" name="radioModifier" value="And"/>
  -      </p>
  -
  -      <p>
  -      Current Query:
  -      <pre id="curQuery"></pre>
  -      </p>
  -
  -      <input type="button" name="Update" value="Update Query" onClick="doMakeQuery(this.form.query); curQuery.innerText = this.form.query.value" />
  -      <input type="button" name="Validate" value="Validate" onClick="doCheckLuceneQuery(this.form.query);" />
  +      <tr><th></th><td></td><td><input type="button" value="Search" onClick="submitForm(this.form)"></td>      
  +    </table>
       </form>
  +    <p>luceneQueryConstructor works by assuming a certain naming convention of form fields to obtain the necessary information to construct the query.<br>
  +    <b>NB:</b>Unless otherwise specified, all uses of the word <code>field</code> should be assumed to mean form input fields and not Lucene document fields.
  +    <p>The input form field is expected to be the <b>same name as the Lucene Field</b>.  For example, if you have a Document with <i>fileName</i> as a Field, and 
  +    you'd like to provide field-searching on this field, then introduce a form field like so:
  +    <center>
  +    <p><code>&lt;input type="text" name="fileName"&gt;</code>
  +    </p>
  +    </center>
  +    You are also expected to provide another field known as 
  +    this field's <b>modifier</b>. This modifier field tells luceneQueryConstructor how to convert the field and value into a Lucene query. The naming convention 
  +    of the modifier is <b>&lt;name of input field/Lucene field&gt;&lt;modifier suffix as declared in luceneQueryConstructor.js&gt;</b>. So, for the <i>fileName</i> field 
  +    we introduced above, it's modifier field would be:
  +    <center>
  +    <p><code>&lt;input type="hidden" name="fileNameModifier" value="+|+"&gt;</code>
  +    </p>
  +    </center>
  +    <p>The value of the modifier field is in the form <b>&lt;term modifier&gt;|&lt;group modifier&gt;</b>. Let me explain.
  +    <p>Looking at the form above, we see fields that provide
  +    <ol>
  +    <li>AND search
  +    <li>OR search
  +    <li>NOT search
  +    <li>and others which are unrelated to this discussion
  +    </ol>
  +    Given a value of <b><i>foo bar</i></b>, the AND search field must be converted to <b><i>+foo +bar</i></b> (luceneQueryConstructor only supports 
  +    using +/-, not AND/OR/NOT), the NOT search to <b><i>-foo -bar</i></b> and the OR search not at all.
  +    <p>However, also consider the relationship <b>between</b> these groups of fields. Assuming Google's Advanced Search interface, 
  +    we're effectively saying that we want all of the terms in the AND search field <b>AND</b> at least one of the 
  +    terms in the OR search field <b>AND</b> none of the terms in the NOT search. 
  +    <p>So, if the AND, OR and NOT search fields all have the values of <b><i>foo bar</i></b>, then an appropriate search query 
  +    which fulfills the requirements would be
  +    <center>
  +    <p><code>+foo +bar +(foo bar) -foo -bar</code>
  +    </p>
  +    </center>
  +    Well, to be more correct, it should be 
  +    <center>
  +    <p><code>+(+foo +bar) +(foo bar) -foo -bar</code>
  +    </p>
  +    </center>
  +    Hmmmm...if you're sharp, you would have noticed that the NOT terms aren't grouped. 
  +    You'll find that if you group them with an AND modifier, no results will be returned at all (though it's a valid query),
  +    because the query constructed wouldn't make any sense at all. Lucene also implicitly ANDs NOT terms, it seems. In any case,
  +    both queries as presented are correct, though I prefer the first one because it is less verbose.
  +    <p>The following matrix provides modifiers and their effects on queries:<br><br>
  +    <table border="1" align="center">
  +    <tr>
  +    <th>Boolean modifier
  +    <th>Form value
  +    <th>As term modifier
  +    <th>As group modifier
  +    </tr>
  +    <tr align="center">
  +    <td>AND
  +    <td>+
  +    <td>+term1 + term2 ...
  +    <td>+(...)
  +    </tr>
  +    <tr align="center">
  +    <td>OR
  +    <td>(single space)
  +    <td>term1  term2 ...
  +    <td>(...)
  +    </tr>
  +    <tr align="center">
  +    <td>NOT
  +    <td>-
  +    <td>-term1  -term2 ...
  +    <td>-(...)
  +    </tr>
  +    <tr align="center">
  +    <td>no modifier
  +    <td>0
  +    <td>term1  term2 ...
  +    <td>no grouping
  +    </tr>
  +    </table>
  +    <p>With this knowledge, we know that the value of the AND field modifier needs to be <b><i>+|0</i></b> for the first query and 
  +    <b><i>+|+</i></b> for the second query, the values of the NOT field modifier and the 
  +    OR field modifier are <b><i>-|0</i></b> and <b><i>&nbsp;|+</i></b> (it's an empty space before the |) in both queries respectively.
  +    <p>
  +    Well, that's all I have to say for now. There are more topics to be covered, such as construction of phrase searches, non-field searches, 
  +    multiple list box selections, radio buttons etc, but right now I'm not even sure if anyone will read this much! :-) Anyway, there's always the code. 
     </body>
   </html>
  
  
  
  1.1                  jakarta-lucene-sandbox/contributions/javascript/queryConstructor/testQueryConstructor.html
  
  Index: testQueryConstructor.html
  ===================================================================
  <html>
  
  <head>
  <script language="JavaScript" src="c:/market/jsunit/app/jsUnitCore.js"></script>
  <script language="JavaScript" src="luceneQueryConstructor.js"></script>
  </head>
  <body>
  <script>
  setAlertUser(false);
  
  // additions to jsUnit
  function assertTrue(comment, value)
  {
    return assertEquals(comment, true, value);
  }
  
  function assertFalse(comment, value)
  {
    return assertEquals(comment, false, value);
  }
  
  function testTrim()
  {
    assertEquals("Not trimming", "foo bar", trim("  foo bar"));
    assertEquals("Not trimming", "foo bar", trim("  foo bar  "));
    assertEquals("Not trimming", "foo bar", trim("  foo   bar  "));
    assertEquals("Not trimming", "foo bar", trim("  foo bar\n\t "));
    assertEquals("Not trimming", "foo:(bar)", trim(" foo:(bar)"));
  }
  
  function testGetFieldValue()
  {
    var frm = document.testQueryConstructor;
    // test radio buttons
    frm.fooRadio[0].checked = true;
    assertEquals("Wrong value for radio button", frm.fooRadio[0].value, getFieldValue(frm.fooRadio));
    frm.fooRadio[0].checked = false;
    frm.fooRadio[1].checked = true;
    assertEquals("Wrong value for radio button", frm.fooRadio[1].value, getFieldValue(frm.fooRadio));
    
    // test checkbox
    frm.fooCheck[0].checked = true;
    assertEquals("Wrong value for checkbox", frm.fooCheck[0].value, getFieldValue(frm.fooCheck));
    frm.fooCheck[0].checked = false;
    frm.fooCheck[1].checked = true;
    assertEquals("Wrong value for checkbox", frm.fooCheck[1].value, getFieldValue(frm.fooCheck));
    
    // test select
    frm.fooSelect.options[0].selected = true;
    assertEquals("Wrong value for select", frm.fooSelect.options[0].value, getFieldValue(frm.fooSelect));
    frm.fooSelect.options[0].selected = false;
    frm.fooSelect.options[1].selected = true;
    assertEquals("Wrong value for checkbox", frm.fooSelect.options[1].value, getFieldValue(frm.fooCheck));
    
    // test text field
    assertEquals("Wrong value for text field", frm.fooText.value, getFieldValue(frm.fooText));
    
    // test hidden field
    assertEquals("Wrong value for hidden field", frm.fooHidden.value, getFieldValue(frm.fooHidden));
    
    // test undefined field
    assertEquals("Wrong value for undefined field", "", getFieldValue(frm.nonexistent)); 
    assertEquals("Wrong value for undefined field", "", getFieldValue(null)); 
  }
  
  function testAppendTerms()
  {
    var frm = document.testQueryConstructor;
    assertEquals("Not appending AND terms correctly", "+fooText:(+1)", appendTerms(frm.query, AND_MODIFIER, frm.fooText.value, frm.fooText.name).value);
    frm.query.value = ''
    assertEquals("Not appending NOT terms correctly", "+fooText:(-1)", appendTerms(frm.query, NOT_MODIFIER, frm.fooText.value, frm.fooText.name).value);
    frm.query.value = ''
    assertEquals("Not appending OR terms correctly", "+fooText:(1)", appendTerms(frm.query, OR_MODIFIER, frm.fooText.value, frm.fooText.name).value);
    frm.query.value = ''
    
    frm.fooText.value = "\"my foo bar\""
    assertEquals("Not appending AND terms correctly", "+fooText:(+\"my foo bar\" )", appendTerms(frm.query, AND_MODIFIER, frm.fooText.value, frm.fooText.name).value);
    frm.fooText.value = "1"
    frm.query.value = ''
    
    assertEquals("Not appending terms correctly", "-fooText:(+1)", appendTerms(frm.query, AND_MODIFIER, frm.fooText.value, frm.fooText.name, NOT_MODIFIER).value);
    frm.query.value = ''
    frm.fooText.value = "1 2 3"
    assertEquals("Not appending terms correctly", "+fooText:(+1 +2 +3)", appendTerms(frm.query, AND_MODIFIER, frm.fooText.value, frm.fooText.name).value);
    frm.query.value = ''
    assertEquals("Not appending terms correctly", "-fooText:(1 2 3)", appendTerms(frm.query, OR_MODIFIER, frm.fooText.value, frm.fooText.name, NOT_MODIFIER).value);
    frm.query.value = ''
    assertEquals("Not appending terms correctly", "-fooText:(-1 -2 -3)", appendTerms(frm.query, NOT_MODIFIER, frm.fooText.value, frm.fooText.name, NOT_MODIFIER, NO_MODIFIER).value);
    frm.query.value = ''
    frm.fooText.value = "1"
    
    assertEquals("Not appending terms correctly(without fields)", "+(+1)", appendTerms(frm.query, AND_MODIFIER, frm.fooText.value).value);
    frm.query.value = ''
    assertEquals("Not appending terms correctly(without fields)", "+(+1)", appendTerms(frm.query, AND_MODIFIER, frm["noField-fooText"].value, "noField-fooText").value);
    frm.query.value = ''
  
    frm.fooText.value = "1 2 3"
    assertEquals("Not appending terms correctly(without fields)", "-1 -2 -3", appendTerms(frm.query, NOT_MODIFIER, frm.fooText.value,"", NO_MODIFIER).value);
    frm.query.value = ''
    assertEquals("Not appending terms correctly(without fields)", "+(+1 +2 +3)", appendTerms(frm.query, AND_MODIFIER, frm.fooText.value).value);
    frm.fooText.value = "1"
    frm.query.value = ''
    
  }
  
  function testDoMakeQuery()
  {
    var frm = document.testQueryConstructor;
    frm.or.value = "orValue";
    assertEquals("Wrong query constructed", "or:(orValue)", doMakeQuery(frm.query).value);
    frm.orModifier.value = " |+";
    assertEquals("Wrong query constructed", "+or:(orValue)", doMakeQuery(frm.query).value);
    frm.orModifier.value = " | ";
    assertEquals("Wrong query constructed", "or:(orValue)", doMakeQuery(frm.query).value);
    frm.orModifier.value = "";
    assertEquals("Wrong query constructed", DEFAULT_GROUP_MODIFIER + "or:(" + DEFAULT_TERM_MODIFIER + "orValue)", doMakeQuery(frm.query).value);
  }
  
  function doANDTerms()
  {
    
  }
  </script>
  
  <form name="testQueryConstructor">
  <input type="radio" name="fooRadio" value="1">
  <input type="radio" name="fooRadio" value="2">
  
  <input type="checkbox" name="fooCheck" value="1">
  <input type="checkbox" name="fooCheck" value="2">
  
  <select name="fooSelect">
  <option value="1">
  <option value="2">
  </select>
  
  <input type="text" name="fooText" value="1">
  <input type="text" name="noField-fooText" value="1">
  <input type="text" name="foobarText" value="1">
  <input type="hidden" name="fooHidden" value="1">
  <input type="password" name="fooPassword">
  <input type="button" name="fooButton" value="I am a button">
  <input type="submit" name="fooSubmit">
  <input type="reset" name="fooReset">
  <input type="file" name="fooFile">
  
  <input type="hidden" name="andModifier" value="+">
  <input type="hidden" name="and">
  
  <input type="hidden" name="notModifier" value="-">
  <input type="hidden" name="not">
  
  <input type="hidden" name="orModifier" value=" | ">
  <input type="hidden" name="or">
  
  <input type="text" name="query">
  </form>
  </body>
  </html>
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: lucene-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: lucene-dev-help@jakarta.apache.org