/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Mozilla Communicator client code. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Alec Flett * Seth Spitzer * David Bienvenu * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ var gTotalSearchTerms=0; var gSearchTermList; var gSearchTerms = new Array; var gSearchRemovedTerms = new Array; var gSearchScope; var gSearchBooleanRadiogroup; var gUniqueSearchTermCounter = 0; // gets bumped every time we add a search term so we can always // dynamically generate unique IDs for the terms. // cache these so we don't have to hit the string bundle for them var gMoreButtonTooltipText; var gLessButtonTooltipText; var gLoading = true; function searchTermContainer() {} searchTermContainer.prototype = { internalSearchTerm : '', internalBooleanAnd : '', // this.searchTerm: the actual nsIMsgSearchTerm object get searchTerm() { return this.internalSearchTerm; }, set searchTerm(val) { this.internalSearchTerm = val; var term = val; // val is a nsIMsgSearchTerm var searchAttribute=this.searchattribute; var searchOperator=this.searchoperator; var searchValue=this.searchvalue; // now reflect all attributes of the searchterm into the widgets if (searchAttribute) searchAttribute.value = term.attrib; if (searchOperator) searchOperator.value = val.op; if (searchValue) searchValue.value = term.value; this.booleanAnd = val.booleanAnd; return val; }, // searchscope - just forward to the searchattribute get searchScope() { if (this.searchattribute) return this.searchattribute.searchScope; return undefined; }, set searchScope(val) { var searchAttribute = this.searchattribute; if (searchAttribute) searchAttribute.searchScope=val; return val; }, saveId: function (element, slot) { this[slot] = element.id; }, getElement: function (slot) { return document.getElementById(this[slot]); }, // three well-defined properties: // searchattribute, searchoperator, searchvalue // the trick going on here is that we're storing the Element's Id, // not the element itself, because the XBL object may change out // from underneath us get searchattribute() { return this.getElement("internalSearchAttributeId"); }, set searchattribute(val) { this.saveId(val, "internalSearchAttributeId"); return val; }, get searchoperator() { return this.getElement("internalSearchOperatorId"); }, set searchoperator(val) { this.saveId(val, "internalSearchOperatorId"); return val; }, get searchvalue() { return this.getElement("internalSearchValueId"); }, set searchvalue(val) { this.saveId(val, "internalSearchValueId"); return val; }, booleanNodes: null, stringBundle: document.getElementById("bundle_search"), get booleanAnd() { return this.internalBooleanAnd; }, set booleanAnd(val) { this.internalBooleanAnd = val; return val; }, save: function () { var searchTerm = this.searchTerm; searchTerm.attrib = this.searchattribute.value; var nsMsgSearchAttrib = Components.interfaces.nsMsgSearchAttrib; if (this.searchattribute.value > nsMsgSearchAttrib.OtherHeader && this.searchattribute.value < nsMsgSearchAttrib.kNumMsgSearchAttributes) searchTerm.arbitraryHeader = this.searchattribute.label; searchTerm.op = this.searchoperator.value; if (this.searchvalue.value) this.searchvalue.save(); else this.searchvalue.saveTo(searchTerm.value); searchTerm.value = this.searchvalue.value; searchTerm.booleanAnd = this.booleanAnd; searchTerm.matchAll = this.matchAll; }, // if you have a search term element with no search term saveTo: function(searchTerm) { this.internalSearchTerm = searchTerm; this.save(); } } var nsIMsgSearchTerm = Components.interfaces.nsIMsgSearchTerm; function initializeSearchWidgets() { gSearchBooleanRadiogroup = document.getElementById("booleanAndGroup"); gSearchTermList = document.getElementById("searchTermList"); // initialize some strings var bundle = document.getElementById('bundle_search'); gMoreButtonTooltipText = bundle.getString('moreButtonTooltipText'); gLessButtonTooltipText = bundle.getString('lessButtonTooltipText'); } function initializeBooleanWidgets() { var booleanAnd = true; var matchAll = false; // get the boolean value from the first term var firstTerm = gSearchTerms[0].searchTerm; if (firstTerm) { booleanAnd = firstTerm.booleanAnd; matchAll = firstTerm.matchAll; } // target radio items have value="and" or value="or" or "all" gSearchBooleanRadiogroup.value = matchAll ? "matchAll" : (booleanAnd ? "and" : "or") var searchTerms = document.getElementById("searchTermList"); if (searchTerms) searchTerms.hidden = matchAll; } function initializeSearchRows(scope, searchTerms) { for (var i = 0; i < searchTerms.Count(); i++) { var searchTerm = searchTerms.QueryElementAt(i, nsIMsgSearchTerm); createSearchRow(i, scope, searchTerm); gTotalSearchTerms++; } initializeBooleanWidgets(); updateRemoveRowButton(); } // enables/disables the less button for the first row of search terms. function updateRemoveRowButton() { var firstListItem = gSearchTermList.getItemAtIndex(0); if (firstListItem) firstListItem.lastChild.lastChild.lastChild.setAttribute("disabled", gTotalSearchTerms == 1); } // Returns the actual list item row index in the list of search rows // that contains the passed in element id. function getSearchRowIndexForElement(aElement) { var listItem = aElement; while (listItem && listItem.localName != "listitem") listItem = listItem.parentNode; return gSearchTermList.getIndexOfItem(listItem); } function onMore(event) { // if we have an event, extract the list row index and use that as the row number // for our insertion point. If there is no event, append to the end.... var rowIndex; if (event) rowIndex = getSearchRowIndexForElement(event.target) + 1; else rowIndex = gSearchTermList.getRowCount(); createSearchRow(rowIndex, gSearchScope, null); gTotalSearchTerms++; updateRemoveRowButton(); // the user just added a term, so scroll to it gSearchTermList.ensureIndexIsVisible(rowIndex); } function onLess(event) { if (event && gTotalSearchTerms > 1) { removeSearchRow(getSearchRowIndexForElement(event.target)); --gTotalSearchTerms; } updateRemoveRowButton(); } // set scope on all visible searchattribute tags function setSearchScope(scope) { gSearchScope = scope; for (var i=0; i