String.prototype.addSlashes = function(){
	return this.replace(/(["\\\.\|\[\]\^\*\+\?\$\(\)])/g, '\\$1');
}
String.prototype.trim = function () {
    return this.replace(/^\s*(\S*(\s+\S+)*)\s*$/, "$1");
};
/*  QcSuggestions JavaScript Class, version 0.0
 *  Updated: 2007-05-24
 *  (c) 2007 QUALCOMM
 *
 * 	Requires prototype framework version 1.5 or greater <http://prototypejs.org>.
 *
/*--------------------------------------------------------------------------*/

/**
 * @classDescription 	Suggestions can be used to generate a list of suggested 
 * 										keywords from a Web service call to a search engine.
 */
QcSuggestions = Class.create();

QcSuggestions.prototype = {
	
	Version: '0.0.0',
	
	/**
	 * Inititializes a new Suggestions. Should be called after the window is loaded.
	 *
	 * @name 		Suggestions.initialize()
	 * @param 	{String} 		instanceName		The name given to the instance variable of this object.
	 * @param 	{String} 		fieldId 				The search input field id.
	 * @param 	{String} 		suggestionsId 	The target element id to insert the list.
	 * @param 	{String} 		urlBase 				The base of the Web Service URL to get the suggestions.
	 * @param 	{Object} 		options 				Configuration options.
	 * @param 	{String} 		options.defaultFieldValue 				Used to change the check for a prepopulated search field value.
	 * @param		{Object} 		options.additionalParameters 			Hash used to add additional parameters to the Web service request
	 * @param 	{Number} 		options.updateThrottle						Control the delay between Ajax calls when keys are pressed in milliseconds.
	 * @param 	{Number} 		options.suggestionCount						The number of suggestions to display.
	 * @param 	{Boolean} 	options.useSuggestionsTimeout			Turn the suggestion timeout on and off.
	 * @param 	{Number} 		options.suggestionsTimeoutDelay		Control the delay for hiding suggestions in milliseconds.
	 * @param		{Function} 	options.responseParser						Process the Ajax response return into a one-dimensional array of 'suggestion' strings.
	 */
	initialize: function(instanceName, fieldId, suggestionsId, urlBase, options) {
		
    this.instanceName = instanceName;
    this.fieldId = fieldId;
		this.suggestionsId = suggestionsId;
		this.urlBase = urlBase;
		this.setOptions(options);
		this.getSuggestionsList();
		// Start event listeners
		Event.observe(this.fieldId, 'keyup', this.handleKeyUp.bind(this));
		Event.observe(this.fieldId, 'focus', this.handleFocus.bind(this));
		Event.observe(this.fieldId, 'blur', this.handleBlur.bind(this));
		// Contains all of the key presses that should 
		// not trigger a request for suggestions
		this._nonSuggestionKeyCodes = [13, 16, 17, 18, 27, 37, 38, 39, 40, 224];
		// Store previous field value
		this._previousFieldValue = '';
	},
	
	/**
	 * Sets the options for Suggestions operations.
	 *
	 * @name 		Suggestions.setOptions()
	 * @param 	{Object} options	Options to set for the operation.
	 */
	setOptions: function(options) {
		this.options = {
			defaultFieldValue: 				'',
			updateThrottle: 					500,
			useSuggestionsTimeout: 		true,
			suggestionsTimeoutDelay: 	10000,
			suggestionCount: 					10,
			limitMatchToBeginning: 		false
		};
		Object.extend(this.options, options || {});
	},
	
	/**
	 * Gets a list of possible suggestions to show user.
	 *
	 * @name 		Suggestions.getSuggestionsList()
	 */
	getSuggestionsList: function() {
		new Ajax.Request(this.urlBase,
			{method:'GET',
			onSuccess:function(transport) {
				this.possibleSuggestions = transport.responseText.split("\r");
			}.bind(this),
			onFailure:function(transport) {
			}.bind(this)});
	},
	
	/**
	 * Handle the key up event for the search field and get suggestions.
	 *
	 * @name 		Suggestions.handleKeyUp()
	 * @param 	{Event} event	The key up event object.
	 */
	handleKeyUp: function(event) {

		if($F(this.fieldId) != '' && $F(this.fieldId) != ' ' && $F(this.fieldId) != this.options.defaultFieldValue) {
			if($F(this.fieldId) != this._previousFieldValue && ! this._nonSuggestionKeyCodes.any(function(keyCode) {return keyCode == Event.keyCode})) {
				clearInterval(this.keyUpTimeoutId);
				this.keyUpTimeoutId = setTimeout(function() {
					this._previousFieldValue = $F(this.fieldId);
					var out = '';
					var suggestions = new Array();
					var input = $F(this.fieldId);
					var inputLength = $F(this.fieldId).length;
					this.possibleSuggestions.each(function(possibleSuggestion, index) {
						if(this.options.limitMatchToBeginning) {
							var re = new RegExp("\\W" + input.addSlashes(), "i");
						} else {  
							var re = new RegExp(input.addSlashes(), "i");
						}
						var m = possibleSuggestion.search(re);
						if(m != -1 && input != '') {
							if(this.options.limitMatchToBeginning) m++;
							var s = '';
							var i;
							for(i = 0; i < m; i++) {
								s += possibleSuggestion.substr(i,1);
							}
							s += '<span class="matched">';
							for(i = m; i < m + inputLength; i++) {
							 	s += possibleSuggestion.substr(i,1);
							}
							s += "</span>";
							for(i = m + inputLength; i < possibleSuggestion.length; i++) {
							 	s += possibleSuggestion.substr(i,1);
							}
							suggestions.push(new Hash({display:s, original:possibleSuggestion.replace(/\n/, '')}));
						}
					}.bind(this));
					
					
					if(suggestions.length > 0) {
						out += '<ul><li style="list-style: none; padding: 0px 0px 0px 0px;">Suggested searches:</li>';
						suggestions.each(function(suggestion, index) {
							if(index < this.options.suggestionCount) {
								if(this.options.useSuggestionsTimeout) {
									var searchfieldId = document.getElementById('searchfield');
									var searchfieldglobalId = document.getElementById('global-search-field');
									if(searchfieldId != null){
										var t = new Template('<li style="list-style: none;"><a href="#" onmouseover="#{instanceName}.clearSuggestionsTimeout(); return false" onmouseout="#{instanceName}.startSuggestionsTimeout(); return false" onclick="document.getElementById(\'searchfield\').focus(); #{instanceName}.setFieldValue(\'#{value}\'); return false">#{display}</a></li>');											
									} else if(searchfieldglobalId != null){
										var t = new Template('<li style="list-style: none;"><a href="#" onmouseover="#{instanceName}.clearSuggestionsTimeout(); return false" onmouseout="#{instanceName}.startSuggestionsTimeout(); return false" onclick="document.getElementById(\'global-search-field\').focus(); #{instanceName}.setFieldValue(\'#{value}\'); return false">#{display}</a></li>');
									}
									out += t.evaluate({instanceName:this.instanceName, value:suggestion['original'], display:suggestion['display']});
								} else {
									var searchfieldId = document.getElementById('searchfield');
									var searchfieldglobalId = document.getElementById('global-search-field');
									if(searchfieldId != null){
										var t = new Template('<li style="list-style: none;"><a href="#" onclick="document.getElementById(\'searchfield\').focus(); #{instanceName}.setFieldValue(\'#{value}\'); return false">#{display}</a></li>');
									}  else if(searchfieldglobalId != null){
										var t = new Template('<li style="list-style: none;"><a href="#" onclick="document.getElementById(\'global-search-field\').focus(); #{instanceName}.setFieldValue(\'#{value}\'); return false">#{display}</a></li>');
									}
									out += t.evaluate({instanceName:this.instanceName, value:suggestion['original'], display:suggestion['display']});
								}
							}
						}.bind(this));
						out += '</ul>';
						if(out != '') $(this.suggestionsId).update(out).show();
						if(this.options.onKeyUped) this.options.onKeyUped();
						this.startSuggestionsTimeout();
					} else {
						this.clearSuggestionsTimeout();
						$(this.suggestionsId).hide().update();
					}
				}.bind(this), this.options.updateThrottle);
			}
		} else {
			$('global-suggestions-iefix').hide();
			$(this.suggestionsId).hide();
		}
	},
	
	/**
	 * Handle the focus event for the search field.
	 *
	 * @name 		Suggestions.handleFocus()
	 * @param 	{Event} event	The focus event for the search field.
	 */
	handleFocus: function(event) {
		this.clearSuggestionsTimeout();
		if($(this.suggestionsId).getElementsBySelector('ul').length > 0 && $F(this.fieldId) != '' && $F(this.fieldId) != this.options.defaultFieldValue) {
			$(this.suggestionsId).show();
			if(this.options.onFocused) {
				this.options.onFocused();
			}
		}
	},
	
	/**
	 * Handle the blur event for the search field.
	 *
	 * @name 		Suggestions.handleBlur()
	 * @param 	{Event} event	The blur event for the search field.
	 */
	handleBlur: function(event) {
		this.clearSuggestionsTimeout();
		if($(this.suggestionsId).getElementsBySelector('ul').length > 0 && $F(this.fieldId) != '' && $F(this.fieldId) != this.options.defaultFieldValue) {
			setTimeout(function() {
				$(this.suggestionsId).hide();
				if(this.options.onBlured) {
					this.options.onBlured();
				}
			}.bind(this), 600);
		} else if($(this.suggestionsId).getElementsBySelector('ul').length > 0 && $F(this.fieldId) == '') {
			setTimeout(function() {
				$(this.suggestionsId).hide().update();
				if(this.options.onBlured) {
					this.options.onBlured();
				}
			}.bind(this), 600);
		}
	},
	
	setFieldValue: function(value) {
		this.clearSuggestionsTimeout();
		$(this.fieldId).value = value;
		$(this.suggestionsId).hide().update();
		if(this.options.onBlured) {
			this.options.onBlured();
		}
	},

	startSuggestionsTimeout: function() {
		this.clearSuggestionsTimeout();
		if(this.options.useSuggestionsTimeout) {
			this.suggestionsTimeoutId = setTimeout(function() {
				$(this.suggestionsId).hide().update();
				if(this.options.onTimeout) {
					this.options.onTimeout();
				}
			}.bind(this), this.options.suggestionsTimeoutDelay);
		}
	},
	
	clearSuggestionsTimeout: function() {
		clearInterval(this.suggestionsTimeoutId);
	}
	
};

/*  QcSuggestions JavaScript Class, version 0.0
 *  Updated: 2007-05-24
 *  (c) 2007 QUALCOMM
 *
 * 	Requires prototype framework version 1.5 or greater <http://prototypejs.org>.
 *
/*--------------------------------------------------------------------------*/

/**
 * @classDescription 	Suggestions can be used to generate a list of suggested 
 * 										keywords from a Web service call to a search engine.
 */
QcSuggestions1 = Class.create();

QcSuggestions1.prototype = {
	
	Version: '0.0.0',
	
	/**
	 * Inititializes a new Suggestions. Should be called after the window is loaded.
	 *
	 * @name 		Suggestions.initialize()
	 * @param 	{String} 		instanceName		The name given to the instance variable of this object.
	 * @param 	{String} 		fieldId 				The search input field id.
	 * @param 	{String} 		suggestionsId 	The target element id to insert the list.
	 * @param 	{String} 		urlBase 				The base of the Web Service URL to get the suggestions.
	 * @param 	{Object} 		options 				Configuration options.
	 * @param 	{String} 		options.defaultFieldValue 				Used to change the check for a prepopulated search field value.
	 * @param 	{Number} 		options.updateThrottle						Control the delay between Ajax calls when keys are pressed in milliseconds.
	 * @param 	{Number} 		options.suggestionCount						The number of suggestions to display.
	 * @param 	{Boolean} 	options.useSuggestionsTimeout			Turn the suggestion timeout on and off.
	 * @param 	{Number} 		options.suggestionsTimeoutDelay		Control the delay for hiding suggestions in milliseconds.
	 * @param		{Function} 	options.responseParser						Process the Ajax response return into a one-dimensional array of 'suggestion' strings.
	 */
	initialize: function(instanceName, fieldId, suggestionsId, urlBase, options) {
    this.instanceName = instanceName;
    this.fieldId = fieldId;
		this.suggestionsId = suggestionsId;
		this.urlBase = urlBase;
		this.setOptions(options);
		// Start event listeners
		Event.observe(this.fieldId, 'keyup', this.handleKeyUp.bind(this));
		Event.observe(this.fieldId, 'focus', this.handleFocus.bind(this));
		Event.observe(this.fieldId, 'blur', this.handleBlur.bind(this));
		// Contains all of the key presses that should 
		// not trigger a request for suggestions
		this._nonSuggestionKeyCodes = [13, 16, 17, 18, 27, 37, 38, 39, 40, 224];
		// Store previous field value
		this._previousFieldValue = '';
	},
	
	/**
	 * Sets the options for Suggestions operations.
	 *
	 * @name 		Suggestions.setOptions()
	 * @param 	{Object} options	Options to set for the operation.
	 */
	setOptions: function(options) {
		this.options = {
			defaultFieldValue: 				'',
			additionalParameters: 		{},
			updateThrottle: 					300,
			useSuggestionsTimeout: 		true,
			suggestionsTimeoutDelay: 	6000,
			suggestionCount: 					10,
			responseParser:function(transport) {
				var suggestions = new Array();
				suggestions = eval(transport.responseText);
				return suggestions.length > 0 ? suggestions : false;
			}
		};
		Object.extend(this.options, options || {});
	},
	
	/**
	 * Handle the key up event for the search field and get suggestions.
	 *
	 * @name 		Suggestions.handleKeyUp()
	 * @param 	{Event} event	The key up event object.
	 */
	handleKeyUp: function(event) {
		if($F(this.fieldId) != '' && $F(this.fieldId) != this.options.defaultFieldValue) {
			if($F(this.fieldId) != this._previousFieldValue && ! this._nonSuggestionKeyCodes.any(function(keyCode) {return keyCode == Event.keyCode})) {
				clearInterval(this.keyUpTimeoutId);
				this.keyUpTimeoutId = setTimeout(function() {
					this._previousFieldValue = $F(this.fieldId);
					new Ajax.Request(this.urlBase + '?' + $H(this.options.additionalParameters).merge($(this.fieldId).serialize().toQueryParams()).toQueryString(),
						{method:'GET',
						onSuccess:function(transport) {
							var out = '';
							var suggestions = new Array();
							suggestions = this.options.responseParser(transport);
							if(suggestions) {
								out += '<ul><li>Suggested searches:</li>';
								suggestions.each(function(suggestion, index) {
									if(index < this.options.suggestionCount) {
										if(this.options.useSuggestionsTimeout) {
											var t = new Template('<li><a href="#" onmouseover="#{instanceName}.clearSuggestionsTimeout(); return false" onmouseout="#{instanceName}.startSuggestionsTimeout(); return false" onclick="#{instanceName}.setFieldValue(\'#{value}\'); return false">#{value}</a></li>');
											out += t.evaluate({instanceName:this.instanceName, value:suggestion});
										} else {
											var t = new Template('<li><a href="#" onclick="#{instanceName}.setFieldValue(\'#{value}\'); return false">#{value}</a></li>');
											out += t.evaluate({instanceName:this.instanceName, value:suggestion});
										}
									}
								}.bind(this));
								out += '</ul>';
								if(out != '') $(this.suggestionsId).update(out).show();
								if(this.options.onKeyUped) {
									this.options.onKeyUped();
								}
								this.startSuggestionsTimeout();
							}
						}.bind(this)});
				}.bind(this), this.options.updateThrottle);
			}
		} else {
			$(this.suggestionsId).hide();
		}
	},
	
	/**
	 * Handle the focus event for the search field.
	 *
	 * @name 		Suggestions.handleFocus()
	 * @param 	{Event} event	The focus event for the search field.
	 */
	handleFocus: function(event) {
		this.clearSuggestionsTimeout();
		if($(this.suggestionsId).getElementsBySelector('ul').length > 0 && $F(this.fieldId) != '' && $F(this.fieldId) != this.options.defaultFieldValue) {
			$(this.suggestionsId).show();
			if(this.options.onFocused) {
				this.options.onFocused();
			}
		}
	},
	
	/**
	 * Handle the blur event for the search field.
	 *
	 * @name 		Suggestions.handleBlur()
	 * @param 	{Event} event	The blur event for the search field.
	 */
	handleBlur: function(event) {
		alert('blur');
		this.clearSuggestionsTimeout();
		if($(this.suggestionsId).getElementsBySelector('ul').length > 0 && $F(this.fieldId) != '' && $F(this.fieldId) != this.options.defaultFieldValue) {
			setTimeout(function() {
				$(this.suggestionsId).hide();
				if(this.options.onBlured) {
					this.options.onBlured();
				}
			}.bind(this), 600);
		} else if($(this.suggestionsId).getElementsBySelector('ul').length > 0 && $F(this.fieldId) == '') {
			setTimeout(function() {
				$(this.suggestionsId).hide().update();
				if(this.options.onBlured) {
					this.options.onBlured();
				}
			}.bind(this), 600);
		}
	},
	
	setFieldValue: function(value) {
		this.clearSuggestionsTimeout();
		$(this.fieldId).value = value;
		$(this.suggestionsId).hide().update();
		if(this.options.onBlured) {
			this.options.onBlured();
		}
	},

	startSuggestionsTimeout: function() {
		this.clearSuggestionsTimeout();
		if(this.options.useSuggestionsTimeout) {
			this.suggestionsTimeoutId = setTimeout(function() {
				$(this.suggestionsId).hide().update();
				if(this.options.onTimeout) {
					this.options.onTimeout();
				}
			}.bind(this), this.options.suggestionsTimeoutDelay);
		}
	},
	
	clearSuggestionsTimeout: function() {
		clearInterval(this.suggestionsTimeoutId);
	}
	
};


/*  QcNavigators JavaScript Class, version 0.0
 *  Updated: 2007-05-24
 *  (c) 2007 QUALCOMM
 *
 * 	Requires prototype framework version 1.5 or greater <http://prototypejs.org>.
 *
/*--------------------------------------------------------------------------*/

/**
 * @classDescription 	Suggestions can be used to generate a list of suggested 
 * 										keywords from a Web service call to a search engine.
 */
var QcNavigators = {
	
	Version: '0.0.0'
	
}

QcNavigators.Base = function() {};
QcNavigators.Base.prototype = {	
	setOptions: function(options) {
		this.options = {
			effect:null
		};
		Object.extend(this.options, options || {});
	},
	calculateRate: function(lineCount) {
		//var rate = 0.04+0.5/Math.pow(Math.E,lineCount);
		var rate = (1+(5/lineCount))*0.03;
		//alert('lineCount:' + lineCount + ', rate:' + rate  );
		return rate;
	}
}

QcNavigators.NavigatorCollection = Class.create();
QcNavigators.NavigatorCollection.prototype = Object.extend(new QcNavigators.Base(), {
	
	initialize: function(instanceName, navigatorsElem, options) {
		this.instanceName = instanceName;
		this.navigatorsElem = Element.extend(navigatorsElem);
		this.navigatorElems = this.navigatorsElem.getElementsBySelector('.navigator');
		this.expandCollapseElem = this.navigatorsElem.down('li.expandcollapse').down('a');
		this.setOptions(options);
		this.navigators = new Array();
		this.navigatorElems.each(function(navigatorElem,index) {
			this.navigators.push(new QcNavigators.Navigator(this.instanceName + '.navigators[' + index + ']', navigatorElem));
		}.bind(this));
		var instanceName = this.instanceName;
		this.expandCollapseElem.onclick = function() {
			eval(instanceName + '.toggleAllNavigators()');
			return false;
		}.bind(this);
		this._canToggleAll = true;
	},
	
	toggleAllNavigators: function() {
		// Prevent double clicking
		if(this._canToggleAll) {
			this._canToggleAll = false;
			// Change the content of anchor depending on current state		
			if(this.expandCollapseElem.hasClassName('expanded')) {
				this.expandCollapseElem.removeClassName('expanded');
				this.expandCollapseElem.update('Expand All');
			} else {
				this.expandCollapseElem.addClassName('expanded');
				this.expandCollapseElem.update('Collapse All');
			}
			// Toggle each navigator			
			this.navigators.each(function(navigator) {
				// Clear current navigator states		
				if(this.expandCollapseElem.hasClassName('expanded')) {
					navigator.navigatorElem.removeClassName('open');
				} else {
					navigator.navigatorElem.addClassName('open');
				}
				var toggleLink = navigator.navigatorElem.getElementsBySelector('h4 a').first();
				if(this.options.effect == 'visibility') {
					navigator.options.effect = 'visibility';
					navigator.toggle(toggleLink);
					navigator.options.effect = '';
				} else {
					navigator.toggle(toggleLink);
				}
			}.bind(this));
			setTimeout(function() {
				this._canToggleAll = true;
			}.bind(this), 300);
		}
	}
	
});


QcNavigators.Navigator = Class.create();
QcNavigators.Navigator.prototype = Object.extend(new QcNavigators.Base(), {
	
	initialize: function(instanceName, navigatorElem, options) {
		this.instanceName = instanceName;
		this.navigatorElem = Element.extend(navigatorElem);
		this.toggleLink = this.navigatorElem.getElementsBySelector('h4 a').first();
		this.contentElem = this.navigatorElem.down('.content');
    this.baseElem = this.contentElem.down('.base');
		this.extendedElem = this.baseElem.next('.extended');
		this.moreElem = this.baseElem.next('.more');
		this.plusMinusElem = this.navigatorElem.down('h4').down('.plusminus');
		this.setOptions(options);
		if(this.toggleLink) {
			var instanceName = this.instanceName;
			this.toggleLink.onclick = function() {
				eval(instanceName + '.toggle(this)');
				return false;
			};
		}
		// Handle subNavigators
		this.subNavigators = new Array();
		if(this.baseElem.getElementsBySelector('.subnavigator').length > 0) {
			this.subNavigatorElems = this.baseElem.getElementsBySelector('.subnavigator');
			if(this.extendedElem && this.extendedElem.getElementsBySelector('.subnavigator').length > 0) {
				this.subNavigatorElems = this.subNavigatorElems.concat(this.extendedElem.getElementsBySelector('.subnavigator'));
			}
			this.subNavigatorElems.each(function(subNavigatorElem,index) {
				this.subNavigators.push(new QcNavigators.SubNavigator(this.instanceName + '.subNavigators[' + index + ']', this,  subNavigatorElem));
			}.bind(this));
		}
		// Handle more items
		if(this.moreElem) {
			this.moreAnchorElem = this.moreElem.getElementsBySelector('.more a').first();
			var instanceName = this.instanceName;
			this.moreAnchorElem.onclick = function() {
				eval(instanceName + '.toggleMore(this)');
				return false;
			};
		}
	},
	
	/**
	 *	Show the base content in a navigator
	**/
	toggle: function(triggerElem) {
		var moreElem = triggerElem.up().next('.content').down('ul.base').next('ul.more');
		if(this.navigatorElem.hasClassName('open')) {
			this.navigatorElem.removeClassName('open');
			this.plusMinusElem.update('[+]');
			if(moreElem) moreElem.hide();
			if(this.options.effect == 'visibility') {
				this.contentElem.hide();
			} else {
				Effect.BlindUp(this.contentElem, {duration:this.toggleDuration()});
			}
		} else {
			this.navigatorElem.addClassName('open');
			this.plusMinusElem.update('[-]');
			if(moreElem) moreElem.show();
			if(this.options.effect == 'visibility') {
				this.contentElem.show();
			} else if(this.options.effect == '' || this.options.effect == null) {
				Effect.BlindDown(this.contentElem, {duration:this.toggleDuration()});
			}
		}
	},
	
	/**
	 *	Calculate the duration of the blind effect for the toggle action
	**/
	toggleDuration: function() {
		var lineCount = 0;
		lineCount = this.baseElem.immediateDescendants().length;
		/*
		if(this.extendedElem && this.moreElem.hasClassName('expanded')) {
			lineCount += this.extendedElem.immediateDescendants().length;
		}
		*/
		lineCount += this.subNavigators.inject(0, function(sum, subNavigator, index) {
			if(subNavigator.subNavigatorElem.hasClassName('open')) {
				if( ! subNavigator.parentListElem.hasClassName('extended')
						|| (subNavigator.parentNavigator.moreElem
									&& subNavigator.parentNavigator.moreElem.hasClassName('expanded'))) {
					return sum + subNavigator.contentElem.immediateDescendants().length;
				}
			}
			return sum;
		});
		return lineCount * this.calculateRate(lineCount);
	},
	
	/**
	 *	Show the extended content in a navigator
	**/
	toggleMore: function(triggerElem) {
		var triggerElem = Element.extend(triggerElem);
		var extendedElem = triggerElem.up().up().previous('.extended');
		var moreElem = triggerElem.up().up('ul.more');
		if(extendedElem) {
			if(moreElem.hasClassName('expanded') ? true : false) {
				moreElem.removeClassName('expanded');
				triggerElem.update('Show more');
				Effect.BlindUp(extendedElem, {duration:this.toggleMoreDuration()});
			} else {
				moreElem.addClassName('expanded');
				triggerElem.update('Show fewer');
				Effect.BlindDown(extendedElem, {duration:this.toggleMoreDuration()});
			}
		}
	},
	
	/**
	 *	Calculate the duration of the blind effect for the toggle more action
	**/
	toggleMoreDuration: function() {
		var lineCount = 0;
		lineCount = this.extendedElem.immediateDescendants().length;
		lineCount += this.subNavigators.inject(0, function(sum, subNavigator, index) {
			if(subNavigator.subNavigatorElem.hasClassName('open')) {
				if(subNavigator.parentNavigator.moreElem.hasClassName('expanded')) {
					return sum + subNavigator.contentElem.immediateDescendants().length;
				}
			}
			return sum;
		});
		return lineCount * this.calculateRate(lineCount);
	}
	
});

QcNavigators.SubNavigator = Class.create();
QcNavigators.SubNavigator.prototype = Object.extend(new QcNavigators.Base(), {
	
	initialize: function(instanceName, parentNavigator, subNavigatorElem, options) {
		this.instanceName = instanceName;
		this.subNavigatorElem = Element.extend(subNavigatorElem);
		this.toggleLink = this.subNavigatorElem.getElementsBySelector('.plusminus a').first();
		this.plusMinusElem = this.subNavigatorElem.getElementsBySelector('.plusminus a').first();
		this.labelElem = this.subNavigatorElem.getElementsBySelector('.plusminus .label').first();
		this.contentElem = this.subNavigatorElem.down('div');
		this.parentNavigator = parentNavigator;
		this.parentListElem = this.subNavigatorElem.up();
		this.baseElem = this.contentElem.down('.base');
		this.extendedElem = this.baseElem.next('.extended');
		this.moreElem = this.contentElem.down('.base').next('.more');
		this.setOptions(options);
		var instanceName = this.instanceName;
		if(this.toggleLink) {
			this.toggleLink.onclick = function() {
				eval(instanceName + '.toggle(this)');
				return false;
			};
		}
		// Handle more
		if(this.moreElem) {
			this.moreAnchorElem = this.moreElem.getElementsBySelector('.more a').first();
			var instanceName = this.instanceName;
			this.moreAnchorElem.onclick = function() {
				eval(instanceName + '.toggleMore(this)');
				return false;
			};
		}
	},
	
	/**
	 *	Show the base content in a subNavigator
	**/
	toggle: function(triggerElem) {
		var triggerElem = Element.extend(triggerElem);
		var moreElem = triggerElem.up().next().down('ul.base').next('ul.more');
		var moreAnchorElem = null;
		if(moreElem) moreAnchorElem = moreElem.down('li').down('a');
		if(this.subNavigatorElem.hasClassName('open')) {
			this.subNavigatorElem.removeClassName('open');
			this.plusMinusElem.update('More [+]');
			if(moreElem) moreElem.hide();
			//moreAnchorElem.update('Show more');
			if(this.options.effect == 'visibility') {
				this.contentElem.hide();
			} else {
				Effect.BlindUp(this.contentElem, {duration:this.toggleDuration()});
			}
		} else {
			this.subNavigatorElem.addClassName('open');
			this.plusMinusElem.update('Fewer [–]');
			if(moreElem) moreElem.show();
			//moreAnchorElem.update('Show fewer');
			if(this.options.effect == 'visibility') {
				this.contentElem.show();
			} else if(this.options.effect == '' || this.options.effect == null) {
				Effect.BlindDown(this.contentElem, {duration:this.toggleDuration()});
			}
		}
	},
	
	/**
	 *	Calculate the duration of the blind effect for the toggle action
	**/
	toggleDuration: function() {
		var lineCount = 0;
		lineCount = this.contentElem.immediateDescendants().inject(lineCount, function(lc, elem) {
			if(elem.visible()) {
				lc += elem.immediateDescendants().length;
			}
			return lc;
		});
//alert(lineCount);
		return lineCount * this.calculateRate(lineCount);
	},
	
	/**
	 *	Show the extended content in a navigator
	**/
	toggleMore: function(triggerElem) {
		var triggerElem = Element.extend(triggerElem);
		var extendedElem = triggerElem.up().up().previous('.extended');
		var moreElem = triggerElem.up().up('ul.more');
		if(extendedElem) {
			if(moreElem.hasClassName('expanded') ? true : false) {
				moreElem.removeClassName('expanded');
				triggerElem.update('Show more');
				Effect.BlindUp(extendedElem, {duration:this.toggleMoreDuration(triggerElem)});
			} else {
				moreElem.addClassName('expanded');
				triggerElem.update('Show fewer');
				Effect.BlindDown(extendedElem, {duration:this.toggleMoreDuration(triggerElem)});
			}
		}
	},
	
	/**
	 *	Calculate the duration of the blind effect for the toggle more action
	**/
	toggleMoreDuration: function(triggerElem) {
		var lineCount = 0;
		var extendedElem = triggerElem.up().up().previous('.extended');
		lineCount = extendedElem.immediateDescendants().length;
		return lineCount * this.calculateRate(lineCount);
	}
	
});