home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / mozil06.zip / bin / chrome / messenger.jar / content / messenger / searchTermOverlay.js < prev    next >
Text File  |  2001-02-14  |  13KB  |  402 lines

  1. /* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public
  4.  * License Version 1.1 (the "License"); you may not use this file
  5.  * except in compliance with the License. You may obtain a copy of
  6.  * the License at http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the License is distributed on an "AS
  9.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  10.  * implied. See the License for the specific language governing
  11.  * rights and limitations under the License.
  12.  *
  13.  * The Original Code is Mozilla Communicator client code.
  14.  *
  15.  * The Initial Developer of the Original Code is Netscape Communications
  16.  * Corporation.  Portions created by Netscape are
  17.  * Copyright (C) 1998 Netscape Communications Corporation. All
  18.  * Rights Reserved.
  19.  *
  20.  * Contributor(s):
  21.  * Alec Flett <alecf@netscape.com>
  22.  */
  23.  
  24. var gTotalSearchTerms=0;
  25. var gSearchRowContainer;
  26. var gSearchTerms = new Array;
  27. var gSearchRemovedTerms = new Array;
  28. var gSearchScope;
  29. var gSearchLessButton;
  30.  
  31. //
  32. function searchTermContainer() {}
  33.  
  34. searchTermContainer.prototype = {
  35.  
  36.     // this.searchTerm: the actual nsIMsgSearchTerm object 
  37.     get searchTerm() { return this.internalSearchTerm; },
  38.     set searchTerm(val) {
  39.         this.internalSearchTerm = val;
  40.         
  41.         var term = val;
  42.         // val is a nsIMsgSearchTerm
  43.         var searchAttribute=this.searchattribute;
  44.         var searchOperator=this.searchoperator;
  45.         var searchValue=this.searchvalue;
  46.  
  47.         // now reflect all attributes of the searchterm into the widgets
  48.         if (searchAttribute) searchAttribute.value = term.attrib;
  49.         if (searchOperator) searchOperator.value = val.op;
  50.         if (searchValue) searchValue.value = term.value;
  51.         
  52.         this.booleanAnd = val.booleanAnd;
  53.         return val;
  54.     },
  55.  
  56.     // searchscope - just forward to the searchattribute
  57.     get searchScope() {
  58.         if (this.searchattribute)
  59.           return this.searchattribute.searchScope;
  60.         return undefined;
  61.     },
  62.     set searchScope(val) {
  63.         var searchAttribute = this.searchattribute;
  64.         if (searchAttribute) searchAttribute.searchScope=val;
  65.         return val;
  66.     },
  67.  
  68.     saveId: function (element, slot) {
  69.         this[slot] = element.id;
  70.     },
  71.  
  72.     getElement: function (slot) {
  73.         return document.getElementById(this[slot]);
  74.     },
  75.  
  76.     // three well-defined properties:
  77.     // searchattribute, searchoperator, searchvalue
  78.     // the trick going on here is that we're storing the Element's Id,
  79.     // not the element itself, because the XBL object may change out
  80.     // from underneath us
  81.     get searchattribute() { return this.getElement("internalSearchAttributeId"); },
  82.     set searchattribute(val) {
  83.         this.saveId(val, "internalSearchAttributeId");
  84.         return val;
  85.     },
  86.     get searchoperator() { return this.getElement("internalSearchOperatorId"); },
  87.     set searchoperator(val) {
  88.         this.saveId(val, "internalSearchOperatorId");
  89.         return val;
  90.     },
  91.     get searchvalue() { return this.getElement("internalSearchValueId"); },
  92.     set searchvalue(val) {
  93.         this.saveId(val, "internalSearchValueId");
  94.         return val;
  95.     },
  96.  
  97.     booleanNodes: null,
  98.     stringBundle: srGetStrBundle("chrome://messenger/locale/search.properties"),
  99.     get booleanAnd() { return this.internalBooleanAnd; },
  100.     set booleanAnd(val) {
  101.         // whenever you set this, all nodes in booleanNodes
  102.         // are updated to reflect the string
  103.         
  104.         if (this.internalBooleanAnd == val) return val;
  105.         this.internalBooleanAnd = val;
  106.         
  107.         var booleanNodes = this.booleanNodes;
  108.         if (!booleanNodes) return val;
  109.         
  110.         var stringBundle = this.stringBundle;
  111.         var andString = val ? "And" : "Or";
  112.         for (var i=0; i<booleanNodes.length; i++) {
  113.             try {              
  114.                 var staticString =
  115.                     stringBundle.GetStringFromName("search" + andString + i);
  116.                 if (staticString && staticString.length>0)
  117.                     booleanNodes[i].setAttribute("value", staticString);
  118.             } catch (ex) { /* no error, means string not found */}
  119.         }
  120.         return val;
  121.     },
  122.  
  123.     save: function () {
  124.         var searchTerm = this.searchTerm;
  125.         searchTerm.attrib = this.searchattribute.value;
  126.         searchTerm.op = this.searchoperator.value;
  127.         if (this.searchvalue.value)
  128.           this.searchvalue.save();
  129.         else
  130.           this.searchvalue.saveTo(searchTerm.value);
  131.         searchTerm.value = this.searchvalue.value;
  132.         searchTerm.booleanAnd = this.booleanAnd;
  133.     },
  134.     // if you have a search term element with no search term
  135.     saveTo: function(searchTerm) {
  136.         this.internalSearchTerm = searchTerm;
  137.         this.save();
  138.     }
  139. }
  140.  
  141. var nsIMsgSearchTerm = Components.interfaces.nsIMsgSearchTerm;
  142.  
  143. function initializeSearchWidgets() {
  144.     gSearchBooleanRadiogroup = document.getElementById("booleanAndGroup");
  145.     gSearchRowContainer = document.getElementById("searchTermList");
  146.     gSearchLessButton = document.getElementById("less");
  147.     if (!gSearchLessButton)
  148.         dump("I couldn't find less button!");
  149. }
  150.  
  151. function initializeBooleanWidgets() {
  152.  
  153.     var booleanAnd = true;
  154.     // get the boolean value from the first term
  155.     var firstTerm = gSearchTerms[0];
  156.     if (firstTerm)
  157.         booleanAnd = firstTerm.booleanAnd;
  158.  
  159.     // target radio items have data="and" or data="or"
  160.     targetValue = "or";
  161.     if (booleanAnd) targetValue = "and";
  162.     
  163.     targetElement = gSearchBooleanRadiogroup.getElementsByAttribute("data", targetValue)[0];
  164.     
  165.     gSearchBooleanRadiogroup.selectedItem = targetElement;
  166. }
  167.  
  168. function initializeSearchRows(scope, searchTerms)
  169. {
  170.     gTotalSearchTerms = searchTerms.Count();
  171.     for (var i=0; i<gTotalSearchTerms; i++) {
  172.         var searchTerm = searchTerms.QueryElementAt(i, nsIMsgSearchTerm);
  173.         createSearchRow(i, scope, searchTerm);
  174.     }
  175.     initializeBooleanWidgets();
  176. }
  177.  
  178. function onMore(event)
  179. {
  180.     if(gTotalSearchTerms==1)
  181.     gSearchLessButton .removeAttribute("disabled", "false");
  182.     createSearchRow(gTotalSearchTerms++, gSearchScope, null);
  183. }
  184.  
  185. function onLess(event)
  186. {
  187.     if (gTotalSearchTerms>1)
  188.         removeSearchRow(--gTotalSearchTerms);
  189.     if (gTotalSearchTerms==1)
  190.         gSearchLessButton .setAttribute("disabled", "true");
  191. }
  192.  
  193. // set scope on all visible searhattribute tags
  194. function setSearchScope(scope) {
  195.     dump("Setting search scope to " + scope + "\n");
  196.     gSearchScope = scope;
  197.     dump("..on " + gSearchTerms.length + " elements.\n");
  198.     for (var i=0; i<gSearchTerms.length; i++) {
  199.         gSearchTerms[i].searchattribute.searchScope = scope;
  200.     }
  201. }
  202.  
  203. function booleanChanged(event) {
  204.     // when boolean changes, we have to update all the attributes on the
  205.     // search terms
  206.  
  207.     var newBoolValue =
  208.         (event.target.getAttribute("data") == "and") ? true : false;
  209.     for (var i=0; i<gSearchTerms.length; i++) {
  210.         var searchTerm = gSearchTerms[i];
  211.         searchTerm.booleanAnd = newBoolValue;
  212.     }
  213.     dump("Boolean is now " + event.target.data + "\n");
  214. }
  215.  
  216.  
  217. function createSearchRow(index, scope, searchTerm)
  218. {
  219.     var searchAttr = document.createElement("searchattribute");
  220.     var searchOp = document.createElement("searchoperator");
  221.     var searchVal = document.createElement("searchvalue");
  222.  
  223.     // now set up ids:
  224.     searchAttr.id = "searchAttr" + index;
  225.     searchOp.id  = "searchOp" + index;
  226.     searchVal.id = "searchVal" + index;
  227.  
  228.     searchAttr.setAttribute("for", searchOp.id + "," + searchVal.id);
  229.  
  230.     var rowdata = new Array(null, searchAttr,
  231.                             null, searchOp,
  232.                             null, searchVal,
  233.                             null);
  234.     var searchrow = constructRow(rowdata);
  235.  
  236.     searchrow.id = "searchRow" + index;
  237.  
  238.     var searchTermObj = new searchTermContainer;
  239.     // is this necessary?
  240.     //searchTermElement.id = "searchTerm" + index;
  241.     gSearchTerms[gSearchTerms.length] = searchTermObj;
  242.     
  243.     searchTermObj.searchattribute = searchAttr;
  244.     searchTermObj.searchoperator = searchOp;
  245.     searchTermObj.searchvalue = searchVal;
  246.  
  247.     // now invalidate the newly created items because they've been inserted
  248.     // into the document, and XBL bindings will be inserted in their place
  249.     //searchAttr = searchOp = searchVal = undefined;
  250.     
  251.     // and/or string handling:
  252.     // this is scary - basically we want to take every other
  253.     // treecell, (note the i+=2) which will be a text label,
  254.     // and set the searchTermObj's
  255.     // booleanNodes to that
  256.     var stringNodes = new Array;
  257.     var treecells = searchrow.firstChild.childNodes;
  258.     var j=0;
  259.     for (var i=0; i<treecells.length; i+=2) {
  260.         stringNodes[j++] = treecells[i];
  261.     }
  262.     searchTermObj.booleanNodes = stringNodes;
  263.     
  264.     gSearchRowContainer.appendChild(searchrow);
  265.  
  266.     dump("createSearchRow: Setting searchScope = " + scope + "\n");
  267.     searchTermObj.searchScope = scope;
  268.     // the search term will initialize the searchTerm element, including
  269.     // .booleanAnd
  270.     if (searchTerm) {
  271.         dump("\nHave a searchterm (" +
  272.              searchTerm.attrib + "/" +
  273.              searchTerm.op + "/" +
  274.              searchTerm.value + ")\n");
  275.         searchTermObj.searchTerm = searchTerm;
  276.     }
  277.     
  278.     // here, we don't have a searchTerm, so it's probably a new element -
  279.     // we'll initialize the .booleanAnd from the existing setting in
  280.     // the UI
  281.     else
  282.         searchTermObj.booleanAnd = getBooleanAnd();
  283.  
  284. }
  285.  
  286. // creates a <treerow> using the array treeCellChildren as 
  287. // the children of each treecell
  288. function constructRow(treeCellChildren)
  289. {
  290.     var treeitem = document.createElement("treeitem");
  291.     var row = document.createElement("treerow");
  292.     for (var i = 0; i<treeCellChildren.length; i++) {
  293.       var treecell = document.createElement("treecell");
  294.       
  295.       // it's ok to have empty cells
  296.       if (treeCellChildren[i]) {
  297.           treecell.setAttribute("allowevents", "true");
  298.           treeCellChildren[i].setAttribute("flex", "1");
  299.           treecell.appendChild(treeCellChildren[i]);
  300.           var child = treeCellChildren[i];
  301.           dump("Appended a " + child.localName + "\n");
  302.           
  303.       }
  304.       row.appendChild(treecell);
  305.     }
  306.     treeitem.appendChild(row);
  307.     return treeitem;
  308. }
  309.  
  310. function removeSearchRow(index)
  311. {
  312.     dump("removing search term " + index + "\n");
  313.     var searchTermObj = gSearchTerms[index];
  314.     if (!searchTermObj) {
  315.         dump("removeSearchRow: couldn't find search term " + index + "\n");
  316.         return;
  317.     }
  318.  
  319.     // need to remove row from tree, so walk upwards from the
  320.     // searchattribute to find the first <treeitem>
  321.     var treeItemRow = searchTermObj.searchattribute;
  322.     //dump("removeSearchRow: " + treeItemRow + "\n");
  323.     while (treeItemRow) {
  324.         if (treeItemRow.localName == "treeitem") break;
  325.         treeItemRow = treeItemRow.parentNode;
  326.     }
  327.  
  328.     if (!treeItemRow) {
  329.         dump("Error: couldn't find parent treeitem!\n");
  330.         return;
  331.     }
  332.  
  333.  
  334.     if (searchTermObj.searchTerm) {
  335.         dump("That was a real row! queuing " + searchTermObj.searchTerm + " for disposal\n");
  336.         gSearchRemovedTerms[gSearchRemovedTerms.length] = searchTermObj.searchTerm;
  337.     } else {
  338.         dump("That wasn't real. ignoring \n");
  339.     }
  340.     
  341.     treeItemRow.parentNode.removeChild(treeItemRow);
  342.     // remove it from the list of terms - XXX this does it?
  343.     dump("Removing row " + index + " from " + gSearchTerms.length + " items\n");
  344.     // remove the last element
  345.     gSearchTerms.length--;
  346.     dump("Now there are " + gSearchTerms.length + " items\n");
  347. }
  348.  
  349. function getBooleanAnd()
  350. {
  351.     if (gSearchBooleanRadiogroup.selectedItem)
  352.         return (gSearchBooleanRadiogroup.selectedItem.getAttribute("data") == "and") ? true : false;
  353.  
  354.     // default to false
  355.     return false;
  356. }
  357.  
  358. // save the search terms from the UI back to the actual search terms
  359. // searchTerms: nsISupportsArray of terms
  360. // termOwner:   object which can contain and create the terms
  361. //              (will be unnecessary if we just make terms creatable
  362. //               via XPCOM)
  363. function saveSearchTerms(searchTerms, termOwner)
  364. {
  365.     
  366.     for (var i = 0; i<gSearchTerms.length; i++) {
  367.         try {
  368.             dump("Saving search element " + i + "\n");
  369.             var searchTerm = gSearchTerms[i].searchTerm;
  370.             if (searchTerm)
  371.                 gSearchTerms[i].save();
  372.             else {
  373.                 // need to create a new searchTerm, and somehow save it to that
  374.                 dump("Need to create searchterm " + i + "\n");
  375.                 searchTerm = termOwner.createTerm();
  376.                 gSearchTerms[i].saveTo(searchTerm);
  377.                 termOwner.appendTerm(searchTerm);
  378.             }
  379.         } catch (ex) {
  380.  
  381.             dump("** Error saving element " + i + ": " + ex + "\n");
  382.         }
  383.     }
  384.  
  385.     // now remove the queued elements
  386.     for (var i=0; i<gSearchRemovedTerms.length; i++) {
  387.         // this is so nasty, we have to iterate through
  388.         // because GetIndexOf is acting funny
  389.         var searchTermSupports =
  390.             gSearchRemovedTerms[i].QueryInterface(Components.interfaces.nsISupports);
  391.         searchTerms.RemoveElement(searchTermSupports);
  392.     }
  393.  
  394. }
  395.  
  396. function onReset(event)
  397. {
  398.     while (gTotalSearchTerms>0)
  399.         removeSearchRow(--gTotalSearchTerms);
  400.     onMore(event);
  401. }
  402.