/* Include this text on your site:

<script language="JavaScript" src="https://www.1-800-Volunteer.org/1800Vol/js/thirdparty.js"></script>
<script language="javascript" type="text/javascript">
	createSearchCustom('https://www.1-800-Volunteer.org','none',true,'none',true,'none',true,'city',0);
</script>

*/

/*function quickSearch(theForm) {
  var zip = theForm.oppSearchZipCode.value;
  var go = true;
  if (zip == null || zip == "" || zip.length != 5)
  {
      alert("Please enter a valid zip code.");
      theForm.oppSearchZipCode.focus();
      go = false;
      return go;
  }
  if (zip.length == 5)
  {
    objRegExp = new RegExp("[0-9]{5}");
    if(zip.search(objRegExp) == -1) { // If invalid
      alert("Please enter a valid zip code.");
      theForm.oppSearchZipCode.focus();
      go = false;
      return go;
    }
  }
  if (go)
  {
    theForm.action="http://www.1-800-volunteer.org/1800Vol/FindOpportunityQuickSearch.do?oppSearchSocialIssue="+theForm.oppSearchSocialIssue.options[theForm.oppSearchSocialIssue.selectedIndex].value+"&oppSearchZipCode="+theForm.oppSearchZipCode.value+"&oppSearchRadius="+theForm.oppSearchRadius.options[theForm.oppSearchRadius.selectedIndex].value;
    return true;
  }
} */

function createSearch() {
  createSearchCustom('http://www.1-800-volunteer.org', 'none', true, 'none', true, 'none', true, 'city', 0);
}

var err_cityState = '\"City & State or Zip Code\" is a required field. Please enter a City & State or a Zip Code.';

function validateCityStateOrZipCode(form,showCityStateOrZipCode){
	if (document.getElementById('keyword') != null && document.getElementById('keyword').value != '' && !doCheckLuceneQuery(document.getElementById('keyword')) ){
		return false;
	}
	if(showCityStateOrZipCode && document.getElementById('cityState').value == ''){
		alert(err_cityState);
		return false;
	}
	return true;
}

function createSearchCustom(nrpSite, keyName, showKeyword, defaultKeywordValue, showCityStateOrZipCode, defaultCityStateOrZipCodeValue, showDistance, defaultDistanceValue, colorScheme){
  var actionToExecute = nrpSite + '/1800Vol';
  if(keyName != 'none')
  	actionToExecute += '/'+keyName;
  actionToExecute += '/FindOpportunityAdvancedSearch.do';
  var colorStyle = '';

  if(colorScheme == 0) { //Set Orange color
		 c_box = 'border: 2px solid #63BAFF; background: #FFE698 url(' + nrpSite + '/1800Vol/images/thirdparty/gradient-orange.gif) repeat-x center top;';
		 c_search1 = nrpSite + '/1800Vol/images/thirdparty/' + 'title-orange-glass.gif';
		 c_search2 = nrpSite + '/1800Vol/images/thirdparty/' + 'title-orange-find-volunteer.gif';
		 c_search3 = nrpSite + '/1800Vol/images/thirdparty/' + 'title-orange-opportunities.gif';
		 c_button = 'color: #174A6D; background: #CAE2F3;';
		 c_powered = 'color: #FF7E00;';

	} else if (colorScheme == 1) { //Set Blue color
		 c_box = 'border: 2px solid #4A74D3; background: #CFE7FF url(' + nrpSite + '/1800Vol/images/thirdparty/gradient-blue.gif) repeat-x center top';
		 c_search1 = nrpSite + '/1800Vol/images/thirdparty/' + 'title-blue-glass.gif';
		 c_search2 = nrpSite + '/1800Vol/images/thirdparty/' + 'title-blue-find-volunteer.gif';
		 c_search3 = nrpSite + '/1800Vol/images/thirdparty/' + 'title-blue-opportunities.gif';
		 c_button = 'color: #174A6D; background: #CAE2F3;';
		 c_powered = 'color: #0026B6;';

	} else if (colorScheme == 2) { //Set Green color
		 c_box = 'border: 2px solid #56CC00; background: #C7FF9E url(' + nrpSite + '/1800Vol/images/thirdparty/gradient-green.gif) repeat-x center top';
		 c_search1 = nrpSite + '/1800Vol/images/thirdparty/' + 'title-green-glass.gif';
		 c_search2 = nrpSite + '/1800Vol/images/thirdparty/' + 'title-green-find-volunteer.gif';
		 c_search3 = nrpSite + '/1800Vol/images/thirdparty/' + 'title-green-opportunities.gif';
		 c_button = 'color: #006633; background: #E7F8DE;';
		 c_powered = 'color: #398A00;';

	} else if (colorScheme == 3) { //Set Red color
		 c_box = 'border: 2px solid #FF3A3A; background: #FFE4E4 url(' + nrpSite + '/1800Vol/images/thirdparty/gradient-red.gif) repeat-x center top';
		 c_search1 = nrpSite + '/1800Vol/images/thirdparty/' + 'title-red-glass.gif';
		 c_search2 = nrpSite + '/1800Vol/images/thirdparty/' + 'title-red-find-volunteer.gif';
		 c_search3 = nrpSite + '/1800Vol/images/thirdparty/' + 'title-red-opportunities.gif';
		 c_button = 'color: #CC0000; background: #F0D4D4;';
		 c_powered = 'color: #EB0000;';
	}

	// ********************************************************
	document.write('<link href="' + nrpSite + '/1800Vol/css/thirdparty.css" rel="stylesheet" type="text/css">');

  document.write('<div class="vol1800-search-box vol1800-medium-box" style="margin-top: 10px; ' + c_box + '">');
  document.write('<form name="advancedSearchForm" id="advancedSearchForm" method="get" action="'+actionToExecute+'" target="_blank" style="display: inline; margin: 0;" onsubmit="return validateCityStateOrZipCode(document.getElementById(\'advancedSearchForm\'),'+showCityStateOrZipCode+');" >');
  document.write('<div class="vol1800-fields-wrapper">');
  document.write('<div style="margin-top: 3px; font-family: Arial, Verdana, Helvetica, sans-serif; font-size: 11px; font-weight: normal; color: #000000; text-align: left;">');
  document.write('<div style="padding: 4px;">');
  document.write('<div style="float: left;"><img src="' + c_search1 + '" alt="" border="0"></div>');
  document.write('<div style="float: left;"><img src="' + c_search2 + '" alt="Find Volunteer" border="0"></div>');
  document.write('<div style="float: left;"><img src="' + c_search3 + '" alt="Opportunities" border="0"></div>');
  document.write('<div style="clear:left"></div></div>');

if(showKeyword){
	document.write('<div style="float: left; padding: 4px;"><label for="keyword">Keyword(s)</label><br>');
	  if(defaultKeywordValue != 'none')
	  	document.write('<input name="keyword" maxlength="55" size="19" value="'+defaultKeywordValue+'" id="keyword" autocomplete="off" type="text" style="font-family: Arial, Helvetica, sans-serif; font-size: 11px;">');
	  else
	  	document.write('<input name="keyword" maxlength="55" size="19 value="" id="keyword" autocomplete="off" type="text" style="font-family: Arial, Helvetica, sans-serif; font-size: 11px;">');

  document.write('<br><div id="suggest"><span id="suggest-label">Suggestions:</span></div>');
  document.write('</div>');
} else {
   	 if(defaultKeywordValue != 'none')
		  document.write('<input name="keyword" id="keyword" value="'+defaultKeywordValue+'" type="hidden">');
}

if(showCityStateOrZipCode){
  document.write('<div style="float: left; padding: 4px;">');
	document.write('<label for="cityState">City &amp; State or Zip Code <span style="color: #FF0000;">*</span></label><br>');
	  if(defaultCityStateOrZipCodeValue != 'none')
	  	document.write('<input name="cityState" maxlength="45" size="20" tabindex="2" id="cityState" value="'+defaultCityStateOrZipCodeValue+'" type="text" style="font-family:Arial, Helvetica, sans-serif; font-size:11px;">');
	  else
	  	document.write('<input name="cityState" maxlength="45" size="20" tabindex="2" id="cityState" value="" type="text" style="font-family:Arial, Helvetica, sans-serif; font-size:11px;">');
  document.write('</div>');
} else {
   	 if(defaultCityStateOrZipCodeValue != 'none')
		  document.write('<input name="cityState" id="cityState" value="'+defaultCityStateOrZipCodeValue+'" type="hidden">');
}

if(showDistance){
  document.write('<div style="float: left; padding: 4px;">');
  document.write('<label for="distance">Distance</label><br>');
  document.write('<select name="distance" id="distance" tabindex="3" style="font-family: Arial, Verdana, Helvetica, sans-serif; font-size: 11px;">');

	  if(defaultDistanceValue == 'city')
		  document.write('<option value="city" selected>City</option>');
	  else
		  document.write('<option value="city">City</option>');

	  if(defaultDistanceValue == 'county')
		  document.write('<option value="county" selected>County</option>');
	  else
		  document.write('<option value="county">County</option>');

	  if(defaultDistanceValue == 'surroundingArea')
		  document.write('<option value="surroundingArea" selected>Surrounding area</option>');
	  else
		  document.write('<option value="surroundingArea">Surrounding area</option>');

	  if(defaultDistanceValue == 'state')
		  document.write('<option value="state" selected>State</option>');
	  else
		  document.write('<option value="state">State</option>');
  document.write('</select>');
  document.write('</div>');
}	else {
	  document.write('<input name="distance" value="'+defaultDistanceValue+'" type="hidden">');
}

  document.write('<div style="float: left; padding: 4px;">');
  document.write('&nbsp;<br>');
  document.write('<input type="submit" name="method" value="Search" class="button" style="font-family: Arial, Verdana, Helvetica, sans-serif; font-size: 11px; ' + c_button + '">');
  document.write('</div>');
  document.write('</div>');
  document.write('<div style="clear: left;"></div>');
  document.write('</div>');
  document.write('<div class="vol1800-powered-by" style="font-family: Arial,Verdana,Helvetica,sans-serif; font-size: 12px; font-weight: bold; background-color: white; ' + c_powered + '">Powered&nbsp;by:<br><a href="http://www.handsonnetwork.org"><img src="http://www.1-800-volunteer.org/1800Vol/images/logos/handsonnetwork.gif" style="margin: 5px 0pt;" border="0"></a></div>');
  document.write('<div style="clear: both;"></div>');
  document.write('</form></div>');



  var list = ['Animal Protection & Welfare',
			'Arts/Culture',
			'Civil/Social Action/Advocacy',
			'Community/Organizational Development',
			'Crime/Legal',
			'Disaster/Emergency',
			'Drug/Alcohol Abuse',
			'Education',
			'Employment/Work',
			'Environment',
			'Health',
			'Homelessness',
			'Housing',
			'Human Services',
			'Hunger/Nutrition',
			'Immigration',
			'Literacy',
			'Mental Health/Crisis Intervention',
			'Mentoring',
			'Recreation',
			'Senior Citizens',
			'Special Events',
			'Teen Pregnancy',
			'Youth Development'];

if(showKeyword){
  new Suggest.Local("keyword", "suggest", list, {highlight: true});
}


}


/* Namespace */
var Vol1800 = {}

Vol1800.Dom = {
  get: function(el) {
    if (typeof el === 'string') {
      return document.getElementById(el);
    } else {
      return el;
    }
  }
};
Vol1800.Event = {
  add: function() {
    if (window.addEventListener) {
      return function(el, type, fn) {
        Vol1800.Dom.get(el).addEventListener(type, fn, false);
      };
    } else if (window.attachEvent) {
      return function(el, type, fn) {
        var f = function() {
          fn.call(Vol1800.Dom.get(el), window.event);
        };
        Vol1800.Dom.get(el).attachEvent('on' + type, f);
      };
    }
  }()
};

Vol1800.getElementsByClassName = function(strClass, strTag, objContElm) {
  strTag = strTag || "*";
  objContElm = objContElm || document;
  var objColl = objContElm.getElementsByTagName(strTag);
  if (!objColl.length &&  strTag == "*" &&  objContElm.all) objColl = objContElm.all;
  var arr = new Array();
  var delim = strClass.indexOf('|') != -1  ? '|' : ' ';
  var arrClass = strClass.split(delim);
  for (var i = 0, j = objColl.length; i < j; i++) {
    var arrObjClass = objColl[i].className.split(' ');
    if (delim == ' ' && arrClass.length > arrObjClass.length) continue;
    var c = 0;
    comparisonLoop:
    for (var k = 0, l = arrObjClass.length; k < l; k++) {
      for (var m = 0, n = arrClass.length; m < n; m++) {
        if (arrClass[m] == arrObjClass[k]) c++;
        if (( delim == '|' && c == 1) || (delim == ' ' && c == arrClass.length)) {
          arr.push(objColl[i]);
          break comparisonLoop;
        }
      }
    }
  }
  return arr;
}

// 4-7-2009 MRT - removed due to conflict with thickbox div overlay feature
// To cover IE 5.0's lack of the push method
//Array.prototype.push = function(value) {
//  this[this.length] = value;
//}


Vol1800.Event.add(window, 'load', function(e) {

	var searchBoxes = Vol1800.getElementsByClassName("vol1800-search-box","DIV");

    for(var i = 0; i < searchBoxes.length; i++)
    {
        var sb = new Vol1800.SearchBox(searchBoxes[i]);
    }
});

Vol1800.SearchBox = function(el) {
    this.el = el;
	var self = this;

	Vol1800.ConfigureSearchBox(this.el);

	// Get: vol1800-powered-by

    Vol1800.Event.add(window, "resize", function(e) {
		Vol1800.ConfigureSearchBox(self.el);
    });
}

Vol1800.ConfigureSearchBox = function(el) {
	if(el.offsetWidth < 375) {
		if(el.className != "vol1800-search-box vol1800-narrow-box")
			el.className = "vol1800-search-box vol1800-narrow-box";
	} else if(el.offsetWidth < 575) {
		if(el.className != "vol1800-search-box vol1800-medium-box")
			el.className = "vol1800-search-box vol1800-medium-box";
	} else {
		if(el.className != "vol1800-search-box vol1800-wide-box")
			el.className = "vol1800-search-box vol1800-wide-box";
	}
}

/*
--------------------------------------------------------
suggest.js - Input Suggest
Version 2.1 (Update 2008/04/02)

Copyright (c) 2006-2008 onozaty (http://www.enjoyxstudy.com)

Released under an MIT-style license.

For details, see the web site:
 http://www.enjoyxstudy.com/javascript/suggest/

--------------------------------------------------------
*/
/* Modified by: Aaron
 * (Oct 2008)
 */

if (!Suggest) {
  var Suggest = {};
}
/*-- KeyCodes -----------------------------------------*/
Suggest.Key = {
  TAB:     9,
  RETURN: 13,
  ESC:    27,
  UP:     38,
  DOWN:   40
};

/*-- Utils --------------------------------------------*/
Suggest.copyProperties = function(dest, src) {
  for (var property in src) {
    dest[property] = src[property];
  }
  return dest;
};

/*-- Suggest.Local ------------------------------------*/
Suggest.Local = function() {
  this.initialize.apply(this, arguments);
};
Suggest.Local.prototype = {
  initialize: function(input, suggestArea, candidateList) {

    this.input = this._getElement(input);
    this.suggestArea = this._getElement(suggestArea);
    this.candidateList = candidateList;
    this.oldText = this.getInputText();

    if (arguments[3]) this.setOptions(arguments[3]);

    // reg event
    this._addEvent(this.input, 'focus', this._bind(this.checkLoop));
    this._addEvent(this.input, 'blur', this._bind(this.inputBlur));

    var keyevent = 'keydown';
    if (window.opera || (navigator.userAgent.indexOf('Gecko') >= 0 && navigator.userAgent.indexOf('KHTML') == -1)) {
      keyevent = 'keypress';
    }
    this._addEvent(this.input, keyevent, this._bindEvent(this.keyEvent));

    // init
    this.clearSuggestArea();
  },

  // options
  interval: 500,
  dispMax: 20,
  listTagName: 'div',
  prefix: false,
  ignoreCase: true,
  highlight: false,
  dispAllKey: false,
  classMouseOver: 'over',
  classSelect: 'select',
  hookBeforeSearch: function(){},

  setOptions: function(options) {
    Suggest.copyProperties(this, options);
  },

  inputBlur: function() {

    this.changeUnactive();
    this.oldText = this.getInputText();

    if (this.timerId) clearTimeout(this.timerId);
    this.timerId = null;

    setTimeout(this._bind(this.clearSuggestArea), 500);
  },

  checkLoop: function() {
    var text = this.getInputText();

    if (text != this.oldText) {
      this.oldText = text;
      this.search();

	// Aaron: We want the box to open if no text, but not to keep refreshing each loop
    } else {
		if ((text == '' || text == null) && this.suggestArea.style.display == 'none') {
			this.oldText = '';
			this.search();
		}
		// End Aaron
	}

    if (this.timerId) clearTimeout(this.timerId);
    this.timerId = setTimeout(this._bind(this.checkLoop), this.interval);
  },

  search: function() {

    // init
    this.clearSuggestArea();

	var text = this.getInputText();

	// Aaron: We want to see the suggestions even if text is blank
    //if (text == '' || text == null) return;

    this.hookBeforeSearch(text);
    var resultList = this._search(text);
    if (resultList != 0) this.createSuggestArea(resultList);
  },

  _search: function(text) {

    var resultList = [];
    var temp;
    this.suggestIndexList = [];

    for (var i = 0, length = this.candidateList.length; i < length; i++) {
      if ((temp = this.isMatch(this.candidateList[i], text)) != null) {
        resultList.push(temp);
        this.suggestIndexList.push(i);

        if (this.dispMax != 0 && resultList.length >= this.dispMax) break;
      }
    }
    return resultList;
  },

  isMatch: function(value, pattern) {

    if (value == null) return null;

    var pos = (this.ignoreCase) ?
      value.toLowerCase().indexOf(pattern.toLowerCase())
      : value.indexOf(pattern);

    if ((pos == -1) || (this.prefix && pos != 0)) return null;

    if (this.highlight) {
      return (this._escapeHTML(value.substr(0, pos)) + '<strong>'
             + this._escapeHTML(value.substr(pos, pattern.length))
               + '</strong>' + this._escapeHTML(value.substr(pos + pattern.length)));
    } else {
      return this._escapeHTML(value);
    }
  },

  clearSuggestArea: function() {
  	// Aaron: Include a label
    this.suggestArea.innerHTML = '<span id="suggest-label">Suggestions:</span>';
    this.suggestArea.style.display = 'none';
    this.suggestList = null;
    this.suggestIndexList = null;
    this.activePosition = null;
  },

  createSuggestArea: function(resultList) {

    this.suggestList = [];
    this.inputValueBackup = this.input.value;

    for (var i = 0, length = resultList.length; i < length; i++) {
      var element = document.createElement(this.listTagName);
      element.innerHTML = resultList[i];
      this.suggestArea.appendChild(element);

      this._addEvent(element, 'click', this._bindEvent(this.listClick, i));
      this._addEvent(element, 'mouseover', this._bindEvent(this.listMouseOver, i));
      this._addEvent(element, 'mouseout', this._bindEvent(this.listMouseOut, i));

      this.suggestList.push(element);
    }

    this.suggestArea.style.display = '';
  },

  getInputText: function() {
    return this.input.value;
  },

  setInputText: function(text) {
    this.input.value = text;
  },

  // key event
  keyEvent: function(event) {

    if (!this.timerId) {
      this.timerId = setTimeout(this._bind(this.checkLoop), this.interval);
    }

    if (this.dispAllKey && event.ctrlKey
        && this.getInputText() == ''
        && !this.suggestList
        && event.keyCode == Suggest.Key.DOWN) {
      // dispAll
      this._stopEvent(event);
      this.keyEventDispAll();
    } else if (event.keyCode == Suggest.Key.UP ||
               event.keyCode == Suggest.Key.DOWN) {
      // key move
      if (this.suggestList && this.suggestList.length != 0) {
        this._stopEvent(event);
        this.keyEventMove(event.keyCode);
      }
    } else if (event.keyCode == Suggest.Key.RETURN) {
      // fix
      if (this.suggestList && this.suggestList.length != 0) {
        this._stopEvent(event);
        this.keyEventReturn();
      }
    } else if (event.keyCode == Suggest.Key.ESC) {
      // cancel
      if (this.suggestList && this.suggestList.length != 0) {
        this._stopEvent(event);
        this.keyEventEsc();
      }
    } else {
      this.keyEventOther(event);
    }
  },

  keyEventDispAll: function() {

    // init
    this.clearSuggestArea();

    this.oldText = this.getInputText();

    this.suggestIndexList = [];
    for (var i = 0, length = this.candidateList.length; i < length; i++) {
      this.suggestIndexList.push(i);
    }

    this.createSuggestArea(this.candidateList);
  },

  keyEventMove: function(keyCode) {

    this.changeUnactive();

    if (keyCode == Suggest.Key.UP) {
      // up
      if (this.activePosition == null) {
        this.activePosition = this.suggestList.length -1;
      }else{
        this.activePosition--;
        if (this.activePosition < 0) {
          this.activePosition = null;
          this.input.value = this.inputValueBackup;
          return;
        }
      }
    }else{
      // down
      if (this.activePosition == null) {
        this.activePosition = 0;
      }else{
        this.activePosition++;
      }

      if (this.activePosition >= this.suggestList.length) {
        this.activePosition = null;
        this.input.value = this.inputValueBackup;
        return;
      }
    }

    this.changeActive(this.activePosition);
  },

  keyEventReturn: function() {

    this.clearSuggestArea();
    this.moveEnd();
  },

  keyEventEsc: function() {

    this.clearSuggestArea();
    this.input.value = this.inputValueBackup;
    this.oldText = this.getInputText();

    if (window.opera) setTimeout(this._bind(this.moveEnd), 5);
  },

  keyEventOther: function(event) {},

  changeActive: function(index) {

    this.setStyleActive(this.suggestList[index]);

    this.setInputText(this.candidateList[this.suggestIndexList[index]]);

    this.oldText = this.getInputText();
    this.input.focus();
  },

  changeUnactive: function() {

    if (this.suggestList != null
        && this.suggestList.length > 0
        && this.activePosition != null) {
      this.setStyleUnactive(this.suggestList[this.activePosition]);
    }
  },

  listClick: function(event, index) {

    this.changeUnactive();
    this.activePosition = index;
    this.changeActive(index);

    this.moveEnd();
  },

  listMouseOver: function(event, index) {
    this.setStyleMouseOver(this._getEventElement(event));
  },

  listMouseOut: function(event, index) {

    if (!this.suggestList) return;

    var element = this._getEventElement(event);

    if (index == this.activePosition) {
      this.setStyleActive(element);
    }else{
      this.setStyleUnactive(element);
    }
  },

  setStyleActive: function(element) {
    element.className = this.classSelect;
  },

  setStyleUnactive: function(element) {
    element.className = '';
  },

  setStyleMouseOver: function(element) {
    element.className = this.classMouseOver;
  },

  moveEnd: function() {

    if (this.input.createTextRange) {
      this.input.focus(); // Opera
      var range = this.input.createTextRange();
      range.move('character', this.input.value.length);
      range.select();
    } else if (this.input.setSelectionRange) {
      this.input.setSelectionRange(this.input.value.length, this.input.value.length);
    }
  },

  // Utils
  _getElement: function(element) {
    return (typeof element == 'string') ? document.getElementById(element) : element;
  },
  _addEvent: (window.addEventListener ?
    function(element, type, func) {
      element.addEventListener(type, func, false);
    } :
    function(element, type, func) {
      element.attachEvent('on' + type, func);
    }),
  _stopEvent: function(event) {
    if (event.preventDefault) {
      event.preventDefault();
      event.stopPropagation();
    } else {
      event.returnValue = false;
      event.cancelBubble = true;
    }
  },
  _getEventElement: function(event) {
    return event.target || event.srcElement;
  },
  _bind: function(func) {
    var self = this;
    var args = Array.prototype.slice.call(arguments, 1);
    return function(){ func.apply(self, args); };
  },
  _bindEvent: function(func) {
    var self = this;
    var args = Array.prototype.slice.call(arguments, 1);
    return function(event){ event = event || window.event; func.apply(self, [event].concat(args)); };
  },
  _escapeHTML: function(value) {
    return value.replace(/\&/g, '&amp;').replace( /</g, '&lt;').replace(/>/g, '&gt;')
             .replace(/\"/g, '&quot;').replace(/\'/g, '&#39;');
  }
};


// JavaScript Lucene Query Validator
// Tested: IE 6.0.2800 and Mozilla Firebird 0.7
// Special characters are + - && || ! ( ) { } [ ] ^ " ~ * ? : \
// Special words are (case-sensitive) AND NOT OR
// Makes wildcard queries case-insensitive if true.
var error_checkAllowedCharacters = 'Invalid Keyword! The allowed characters are a-z A-Z 0-9.  \\_ \\+ \\- () \\" \\& \\| \\[ \\] \\\ @ \\= \\# \\% \\$ \\\' \\, \\/ . Please try again.';
var error_checkAsterisk = 'Invalid Keyword! The wildcard (*) is not allowed. Please try again.';
var error_checkAmpersands = 'Invalid Keyword! Queries containing the special characters && must be in the form: term1 && term2. Please try again.';
var error_checkCaret = 'Invalid Keyword! The caret (^) character must be preceded by alphanumeric characters and followed by numbers. Please try again.';
var error_checkSquiggle = 'Invalid Keyword! The tilde (~) character must be preceded by alphanumeric characters and followed by numbers. Please try again.';
var error_checkExclamationMark = 'Invalid Keyword! Queries containing the special character ! must be in the form: term1 ! term2. Please try again.';
var error_checkQuestionMark = 'Invalid Keyword! The question mark (?) character must be preceded by at least one alphanumeric character. Please try again.';
var error_checkParentheses1 = 'Invalid Keyword! Parentheses must be closed. Please try again.';
var error_checkParentheses2 = 'Invalid Keyword! Parentheses must contain at least one character. Please try again.';
var error_checkPlusMinus = 'Invalid Keyword! \\\'+\\\' and \\\'-\\\' modifiers must be followed by at least one alphanumeric character. Please try again.';
var error_checkANDORNOT = 'Invalid Keyword!  Queries containing AND/OR must be in the form: term1 AND|OR|AND NOT term2 Please try again.';
var error_checkQuotes1 = 'Invalid Keyword! Please close all quote (\") marks.';
var error_checkQuotes2 = 'Invalid Keyword! Quotes must contain at least one character. Please try again.';
var error_checkColon = 'Invalid Keyword! Field declarations (:) must be preceded by at least one alphanumeric character and followed by at least one alphanumeric character. Please try again.';
var error_checkComma = 'Invalid Keyword! Queries containing the comma characters (,) must be in the form: term1, term2. Please try again.';
var wildcardCaseInsensitive = true;

// Mutator method for wildcardCaseInsensitive.
// @param Should wildcard queries be case-insensitive?
function setWildcardCaseInsensitive(bool)
{
  wildcardCaseInsensitive = bool;
}

// Should the user be prompted with an alert box if validation fails?
var alertUser = true;

function setAlertUser(bool)
{
  alertUser = bool;
}

// validates a lucene query.
// @param Form field that contains the query
function doCheckLuceneQuery(queryField)
{
  return doCheckLuceneQueryValue(queryField.value)
}

// validates a lucene query.
// @param query string
function doCheckLuceneQueryValue(query)
{
  query = trim(query);
  if(query != null && query.length > 0)
  {
    query = removeEscapes(query);

    // check for allowed characters
    if(!checkAllowedCharacters(query)) return false;

    // check * is used properly
    if(!checkAsterisk(query)) return false;

    // check for && usage
    if(!checkAmpersands(query)) return false;

    // check ^ is used properly
    if(!checkCaret(query)) return false;

    // check ~ is used properly
    if(!checkSquiggle(query)) return false;

    // check ! is used properly
    if(!checkExclamationMark(query)) return false;

    // check , is used properly
    if(!checkCommaMark(query)) return false;

    // check question marks are used properly
    if(!checkQuestionMark(query)) return false;

    // check parentheses are used properly
    if(!checkParentheses(query)) return false;

    // check '+' and '-' are used properly
    if(!checkPlusMinus(query)) return false;

    // check AND, OR and NOT are used properly
    if(!checkANDORNOT(query)) return false;

    // check that quote marks are closed
    if(!checkQuotes(query)) return false;

    // check ':' is used properly
    if(!checkColon(query)) return false;

    if(wildcardCaseInsensitive)
    {
      if(query.indexOf("*") != -1)
      {
        var i = query.indexOf(':');
        if(i == -1)
        {
          query.value = query.toLowerCase();
        }
        else // found a wildcard field search
        {
          query.value = query.substring(0, i) + query.substring(i).toLowerCase();
        }
      }
    }
    return true;
  }
}

// remove the escape character and the character immediately following it
function removeEscapes(query)
{
  return query.replace(/\\./g, "");
}
function checkAllowedCharacters(query)
{
  //matches = query.match(/[^a-zA-Z0-9_+\-:.()\"*?&|!{}\[\]\^~\\@#\/$%'=, ]/);
  matches = query.match(/[^a-zA-Z0-9_+\-.()\"&|{}\[\]@#\/$%'=, ]/);
  if(matches != null && matches.length > 0)
  {
    if(alertUser) alert(error_checkAllowedCharacters)
    return false;
  }
  return true;
}

function checkAsterisk(query)
{
  //matches = query.match(/^[\*]*$|[\s]\*|^\*[^\s]/);
  if(query.indexOf("*") > -1)
  {
   // if(alertUser) alert("Invalid Keyword! The wildcard (*) character must be preceded by at least one alphanumeric character. Please try again.")
    if(alertUser) alert(error_checkAsterisk)
    return false;
  }
  return true;
}

function checkAmpersands(query)
{
  // NB: doesn't handle term1 && term2 && term3 in Firebird 0.7
  matches = query.match(/[&]{2}/);
  if(matches != null && matches.length > 0)
  {
    matches = query.match(/^([a-zA-Z0-9_+\-:.()\"*?&|!{}\[\]\^~\\@#\/$%'=]+( && )?[a-zA-Z0-9_+\-:.()\"*?|!{}\[\]\^~\\@#\/$%'=]+[ ]*)+$/); // note missing & in pattern
    if(matches == null)
    {
      if(alertUser) alert(error_checkAmpersands)
      return false;
    }
  }
  return true;
}

function checkCaret(query)
{
//  matches = query.match(/^[^\^]*$|^([a-zA-Z0-9_+\-:.()\"*?&|!{}\[\]\~\\@#\/]+(\^[\d]+)?[ ]*)+$/); // note missing ^ in pattern
  matches = query.match(/^(\^)|[^\\]\^([^\s]*[^0-9.]+)|[^\\]\^$/);
  if(matches != null)
  {
    if(alertUser) alert(error_checkCaret)
    return false;
  }
  return true;
}

function checkSquiggle(query)
{
  //matches = query.match(/^[^~]*$|^([a-zA-Z0-9_+\-:.()\"*?&|!{}\[\]\^\\@#\/]+(~[\d.]+|[^\\]\\~)?[ ]*)+$/); // note missing ~ in pattern
  matches = query.match(/[^\\]~[^\s]*[^0-9\s]+/);
  if(matches != null)
  {
    if(alertUser) alert(error_checkSquiggle)
    return false;
  }
  return true;
}

function checkExclamationMark(query)
{
  // foo! is not a query, but !foo is. hmmmm...
  // NB: doesn't handle term1 ! term2 ! term3 or term1 !term2
  matches = query.match(/^[^!]*$|^([a-zA-Z0-9_+\-:.()\"*?&|!{}\[\]\^~\\@#\/$%'=]+( ! )?[a-zA-Z0-9_+\-:.()\"*?&|!{}\[\]\^~\\@#\/$%'=]+[ ]*)+$/);
  if(matches == null || matches.length == 0)
  {
    if(alertUser) alert(error_checkExclamationMark)
    return false;
  }


  return true;
}

function checkCommaMark(query)
{
  matches = query.match(/(^,)|(,$)/);

  if( matches != null && matches.length > 0 )
  {
    if(alertUser) alert(error_checkComma)
    	return false;
  }
  return true;
}

function checkQuestionMark(query)
{
  matches = query.match(/^(\?)|([^a-zA-Z0-9_+\-:.()\"*?&|!{}\[\]\^~\\@#\/$%'=]\?+)/);
  if(matches != null && matches.length > 0)
  {
      if(alertUser) alert(error_checkQuestionMark)
    return false;
  }
  return true;
}

function checkParentheses(query)
{
  var hasLeft = false;
  var hasRight = false;
  matchLeft = query.match(/[(]/g);
  if(matchLeft != null) hasLeft = true
  matchRight = query.match(/[)]/g);
  if(matchRight != null) hasRight = true;

  if(hasLeft || hasRight)
  {
    if(hasLeft && !hasRight || hasRight && !hasLeft)
    {
        if(alertUser) alert(error_checkParentheses1)
        return false;
    }
    else
    {
      var number = matchLeft.length + matchRight.length;
      if((number % 2) > 0 || matchLeft.length != matchRight.length)
      {
        if(alertUser) alert(error_checkParentheses1)
        return false;
      }
    }
    matches = query.match(/\(\)/);
    if(matches != null)
    {
      if(alertUser) alert(error_checkParentheses2)
      return false;
    }
  }
  return true;
}

function checkPlusMinus(query)
{
  matches = query.match(/^[^\n+\-]*$|^([+-]?[a-zA-Z0-9_:.()\"*?&|!{}\[\]\^~\\@#\/$%'=]+[ ]?)+$/);
  if(matches == null || matches.length == 0)
  {
    if(alertUser) alert(error_checkPlusMinus);
    return false;
  }
  return true;
}

function checkANDORNOT(query)
{
  matches = query.match(/AND|OR|NOT/);
  if(matches != null && matches.length > 0)
  {
    matches = query.match(/^([a-zA-Z0-9_+\-:.()\"*?&|!{}\[\]\^~\\@\/#$%'=]+\s*((AND )|(OR )|(AND NOT )|(NOT ))?[a-zA-Z0-9_+\-:.()\"*?&|!{}\[\]\^~\\@\/#$%'=]+[ ]*)+$/);
    if(matches == null || matches.length == 0)
    {
      if(alertUser) alert(error_checkANDORNOT)
      return false;
    }

    // its difficult to distinguish AND/OR/... from the usual [a-zA-Z] because they're...words!
    matches = query.match(/^((AND )|(OR )|(AND NOT ))|((AND)|(OR)|(AND NOT )|(NOT))[ ]*$/)
    if(matches != null && matches.length > 0)
    {
      if(alertUser) alert(error_checkANDORNOT)
      return false;
    }
  }
  return true;
}

function checkQuotes(query)
{
  matches = query.match(/\"/g);
  if(matches != null && matches.length > 0)
  {
    var number = matches.length;
    if((number % 2) > 0)
    {
      if(alertUser) alert(error_checkQuotes1);
      return false;
    }
    matches = query.match(/""/);
    if(matches != null)
    {
      if(alertUser) alert(error_checkQuotes2)
      return false;
    }
  }
  return true;
}

function checkColon(query)
{
  matches = query.match(/[^\\\s]:[\s]|[^\\\s]:$|[\s][^\\]?:|^[^\\\s]?:/);
  if(matches != null)
  {
    if(alertUser) alert(error_checkColon)
    return false;
  }
  return true;
}
function ltrim(sValue)
{
   while(1)
   {
      if(sValue.substring(0, 1) != " ")
         break;
      sValue = sValue.substring(1, sValue.length);
   }
   return sValue;
}

function rtrim(sValue)
{
   while(1)
   {
      if(sValue.substring(sValue.length - 1, sValue.length) != " ")
         break;
      sValue = sValue.substring(0, sValue.length - 1);
   }
   return sValue;
}
function trim(sValue)
{
   var sTemp = ltrim(sValue);
   return rtrim(sTemp);
}

