| // This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure | 
| // Natural Docs is licensed under the GPL | 
|   | 
|   | 
| // | 
| //  Browser Styles | 
| // ____________________________________________________________________________ | 
|   | 
| var agt=navigator.userAgent.toLowerCase(); | 
| var browserType; | 
| var browserVer; | 
|   | 
| if (agt.indexOf("opera") != -1) | 
|     { | 
|     browserType = "Opera"; | 
|   | 
|     if (agt.indexOf("opera 7") != -1 || agt.indexOf("opera/7") != -1) | 
|         {  browserVer = "Opera7";  } | 
|     else if (agt.indexOf("opera 8") != -1 || agt.indexOf("opera/8") != -1) | 
|         {  browserVer = "Opera8";  } | 
|     else if (agt.indexOf("opera 9") != -1 || agt.indexOf("opera/9") != -1) | 
|         {  browserVer = "Opera9";  } | 
|     } | 
|   | 
| else if (agt.indexOf("applewebkit") != -1) | 
|     { | 
|     browserType = "Safari"; | 
|   | 
|     if (agt.indexOf("version/3") != -1) | 
|         {  browserVer = "Safari3";  } | 
|     else if (agt.indexOf("safari/4") != -1) | 
|         {  browserVer = "Safari2";  } | 
|     } | 
|   | 
| else if (agt.indexOf("khtml") != -1) | 
|     { | 
|     browserType = "Konqueror"; | 
|     } | 
|   | 
| else if (agt.indexOf("msie") != -1) | 
|     { | 
|     browserType = "IE"; | 
|   | 
|     if (agt.indexOf("msie 6") != -1) | 
|         {  browserVer = "IE6";  } | 
|     else if (agt.indexOf("msie 7") != -1) | 
|         {  browserVer = "IE7";  } | 
|     } | 
|   | 
| else if (agt.indexOf("gecko") != -1) | 
|     { | 
|     browserType = "Firefox"; | 
|   | 
|     if (agt.indexOf("rv:1.7") != -1) | 
|         {  browserVer = "Firefox1";  } | 
|     else if (agt.indexOf("rv:1.8)") != -1 || agt.indexOf("rv:1.8.0") != -1) | 
|         {  browserVer = "Firefox15";  } | 
|     else if (agt.indexOf("rv:1.8.1") != -1) | 
|         {  browserVer = "Firefox2";  } | 
|     } | 
|   | 
|   | 
| // | 
| //  Support Functions | 
| // ____________________________________________________________________________ | 
|   | 
|   | 
| function GetXPosition(item) | 
|     { | 
|     var position = 0; | 
|   | 
|     if (item.offsetWidth != null) | 
|         { | 
|         while (item != document.body && item != null) | 
|             { | 
|             position += item.offsetLeft; | 
|             item = item.offsetParent; | 
|             }; | 
|         }; | 
|   | 
|     return position; | 
|     }; | 
|   | 
|   | 
| function GetYPosition(item) | 
|     { | 
|     var position = 0; | 
|   | 
|     if (item.offsetWidth != null) | 
|         { | 
|         while (item != document.body && item != null) | 
|             { | 
|             position += item.offsetTop; | 
|             item = item.offsetParent; | 
|             }; | 
|         }; | 
|   | 
|     return position; | 
|     }; | 
|   | 
|   | 
| function MoveToPosition(item, x, y) | 
|     { | 
|     // Opera 5 chokes on the px extension, so it can use the Microsoft one instead. | 
|   | 
|     if (item.style.left != null) | 
|         { | 
|         item.style.left = x + "px"; | 
|         item.style.top = y + "px"; | 
|         } | 
|     else if (item.style.pixelLeft != null) | 
|         { | 
|         item.style.pixelLeft = x; | 
|         item.style.pixelTop = y; | 
|         }; | 
|     }; | 
|   | 
|   | 
| // | 
| //  Menu | 
| // ____________________________________________________________________________ | 
|   | 
|   | 
| function ToggleMenu(id) | 
|     { | 
|     if (!window.document.getElementById) | 
|         {  return;  }; | 
|   | 
|     var display = window.document.getElementById(id).style.display; | 
|   | 
|     if (display == "none") | 
|         {  display = "block";  } | 
|     else | 
|         {  display = "none";  } | 
|   | 
|     window.document.getElementById(id).style.display = display; | 
|     } | 
|   | 
| function HideAllBut(ids, max) | 
|     { | 
|     if (document.getElementById) | 
|         { | 
|         ids.sort( function(a,b) { return a - b; } ); | 
|         var number = 1; | 
|   | 
|         while (number < max) | 
|             { | 
|             if (ids.length > 0 && number == ids[0]) | 
|                 {  ids.shift();  } | 
|             else | 
|                 { | 
|                 document.getElementById("MGroupContent" + number).style.display = "none"; | 
|                 }; | 
|   | 
|             number++; | 
|             }; | 
|         }; | 
|     } | 
|   | 
|   | 
| // | 
| //  Tooltips | 
| // ____________________________________________________________________________ | 
|   | 
|   | 
| var tooltipTimer = 0; | 
|   | 
| function ShowTip(event, tooltipID, linkID) | 
|     { | 
|     if (tooltipTimer) | 
|         {  clearTimeout(tooltipTimer);  }; | 
|   | 
|     var docX = event.clientX + window.pageXOffset; | 
|     var docY = event.clientY + window.pageYOffset; | 
|   | 
|     var showCommand = "ReallyShowTip('" + tooltipID + "', '" + linkID + "', " + docX + ", " + docY + ")"; | 
|   | 
|     tooltipTimer = setTimeout(showCommand, 1000); | 
|     } | 
|   | 
| function ReallyShowTip(tooltipID, linkID, docX, docY) | 
|     { | 
|     tooltipTimer = 0; | 
|   | 
|     var tooltip; | 
|     var link; | 
|   | 
|     if (document.getElementById) | 
|         { | 
|         tooltip = document.getElementById(tooltipID); | 
|         link = document.getElementById(linkID); | 
|         } | 
| /*    else if (document.all) | 
|         { | 
|         tooltip = eval("document.all['" + tooltipID + "']"); | 
|         link = eval("document.all['" + linkID + "']"); | 
|         } | 
| */ | 
|     if (tooltip) | 
|         { | 
|         var left = GetXPosition(link); | 
|         var top = GetYPosition(link); | 
|         top += link.offsetHeight; | 
|   | 
|   | 
|         // The fallback method is to use the mouse X and Y relative to the document.  We use a separate if and test if its a number | 
|         // in case some browser snuck through the above if statement but didn't support everything. | 
|   | 
|         if (!isFinite(top) || top == 0) | 
|             { | 
|             left = docX; | 
|             top = docY; | 
|             } | 
|   | 
|         // Some spacing to get it out from under the cursor. | 
|   | 
|         top += 10; | 
|   | 
|         // Make sure the tooltip doesnt get smushed by being too close to the edge, or in some browsers, go off the edge of the | 
|         // page.  We do it here because Konqueror does get offsetWidth right even if it doesnt get the positioning right. | 
|   | 
|         if (tooltip.offsetWidth != null) | 
|             { | 
|             var width = tooltip.offsetWidth; | 
|             var docWidth = document.body.clientWidth; | 
|   | 
|             if (left + width > docWidth) | 
|                 {  left = docWidth - width - 1;  } | 
|   | 
|             // If there's a horizontal scroll bar we could go past zero because it's using the page width, not the window width. | 
|             if (left < 0) | 
|                 {  left = 0;  }; | 
|             } | 
|   | 
|         MoveToPosition(tooltip, left, top); | 
|         tooltip.style.visibility = "visible"; | 
|         } | 
|     } | 
|   | 
| function HideTip(tooltipID) | 
|     { | 
|     if (tooltipTimer) | 
|         { | 
|         clearTimeout(tooltipTimer); | 
|         tooltipTimer = 0; | 
|         } | 
|   | 
|     var tooltip; | 
|   | 
|     if (document.getElementById) | 
|         {  tooltip = document.getElementById(tooltipID); } | 
|     else if (document.all) | 
|         {  tooltip = eval("document.all['" + tooltipID + "']");  } | 
|   | 
|     if (tooltip) | 
|         {  tooltip.style.visibility = "hidden";  } | 
|     } | 
|   | 
|   | 
| // | 
| //  Blockquote fix for IE | 
| // ____________________________________________________________________________ | 
|   | 
|   | 
| function NDOnLoad() | 
|     { | 
|     if (browserVer == "IE6") | 
|         { | 
|         var scrollboxes = document.getElementsByTagName('blockquote'); | 
|   | 
|         if (scrollboxes.item(0)) | 
|             { | 
|             NDDoResize(); | 
|             window.onresize=NDOnResize; | 
|             }; | 
|         }; | 
|     }; | 
|   | 
|   | 
| var resizeTimer = 0; | 
|   | 
| function NDOnResize() | 
|     { | 
|     if (resizeTimer != 0) | 
|         {  clearTimeout(resizeTimer);  }; | 
|   | 
|     resizeTimer = setTimeout(NDDoResize, 250); | 
|     }; | 
|   | 
|   | 
| function NDDoResize() | 
|     { | 
|     var scrollboxes = document.getElementsByTagName('blockquote'); | 
|   | 
|     var i; | 
|     var item; | 
|   | 
|     i = 0; | 
|     while (item = scrollboxes.item(i)) | 
|         { | 
|         item.style.width = 100; | 
|         i++; | 
|         }; | 
|   | 
|     i = 0; | 
|     while (item = scrollboxes.item(i)) | 
|         { | 
|         item.style.width = item.parentNode.offsetWidth; | 
|         i++; | 
|         }; | 
|   | 
|     clearTimeout(resizeTimer); | 
|     resizeTimer = 0; | 
|     } | 
|   | 
|   | 
|   | 
| /* ________________________________________________________________________________________________________ | 
|   | 
|     Class: SearchPanel | 
|     ________________________________________________________________________________________________________ | 
|   | 
|     A class handling everything associated with the search panel. | 
|   | 
|     Parameters: | 
|   | 
|         name - The name of the global variable that will be storing this instance.  Is needed to be able to set timeouts. | 
|         mode - The mode the search is going to work in.  Pass <NaturalDocs::Builder::Base->CommandLineOption()>, so the | 
|                    value will be something like "HTML" or "FramedHTML". | 
|   | 
|     ________________________________________________________________________________________________________ | 
| */ | 
|   | 
|   | 
| function SearchPanel(name, mode, resultsPath) | 
|     { | 
|     if (!name || !mode || !resultsPath) | 
|         {  alert("Incorrect parameters to SearchPanel.");  }; | 
|   | 
|   | 
|     // Group: Variables | 
|     // ________________________________________________________________________ | 
|   | 
|     /* | 
|         var: name | 
|         The name of the global variable that will be storing this instance of the class. | 
|     */ | 
|     this.name = name; | 
|   | 
|     /* | 
|         var: mode | 
|         The mode the search is going to work in, such as "HTML" or "FramedHTML". | 
|     */ | 
|     this.mode = mode; | 
|   | 
|     /* | 
|         var: resultsPath | 
|         The relative path from the current HTML page to the results page directory. | 
|     */ | 
|     this.resultsPath = resultsPath; | 
|   | 
|     /* | 
|         var: keyTimeout | 
|         The timeout used between a keystroke and when a search is performed. | 
|     */ | 
|     this.keyTimeout = 0; | 
|   | 
|     /* | 
|         var: keyTimeoutLength | 
|         The length of <keyTimeout> in thousandths of a second. | 
|     */ | 
|     this.keyTimeoutLength = 500; | 
|   | 
|     /* | 
|         var: lastSearchValue | 
|         The last search string executed, or an empty string if none. | 
|     */ | 
|     this.lastSearchValue = ""; | 
|   | 
|     /* | 
|         var: lastResultsPage | 
|         The last results page.  The value is only relevant if <lastSearchValue> is set. | 
|     */ | 
|     this.lastResultsPage = ""; | 
|   | 
|     /* | 
|         var: deactivateTimeout | 
|   | 
|         The timeout used between when a control is deactivated and when the entire panel is deactivated.  Is necessary | 
|         because a control may be deactivated in favor of another control in the same panel, in which case it should stay | 
|         active. | 
|     */ | 
|     this.deactivateTimout = 0; | 
|   | 
|     /* | 
|         var: deactivateTimeoutLength | 
|         The length of <deactivateTimeout> in thousandths of a second. | 
|     */ | 
|     this.deactivateTimeoutLength = 200; | 
|   | 
|   | 
|   | 
|   | 
|     // Group: DOM Elements | 
|     // ________________________________________________________________________ | 
|   | 
|   | 
|     // Function: DOMSearchField | 
|     this.DOMSearchField = function() | 
|         {  return document.getElementById("MSearchField");  }; | 
|   | 
|     // Function: DOMSearchType | 
|     this.DOMSearchType = function() | 
|         {  return document.getElementById("MSearchType");  }; | 
|   | 
|     // Function: DOMPopupSearchResults | 
|     this.DOMPopupSearchResults = function() | 
|         {  return document.getElementById("MSearchResults");  }; | 
|   | 
|     // Function: DOMPopupSearchResultsWindow | 
|     this.DOMPopupSearchResultsWindow = function() | 
|         {  return document.getElementById("MSearchResultsWindow");  }; | 
|   | 
|     // Function: DOMSearchPanel | 
|     this.DOMSearchPanel = function() | 
|         {  return document.getElementById("MSearchPanel");  }; | 
|   | 
|   | 
|   | 
|   | 
|     // Group: Event Handlers | 
|     // ________________________________________________________________________ | 
|   | 
|   | 
|     /* | 
|         Function: OnSearchFieldFocus | 
|         Called when focus is added or removed from the search field. | 
|     */ | 
|     this.OnSearchFieldFocus = function(isActive) | 
|         { | 
|         this.Activate(isActive); | 
|         }; | 
|   | 
|   | 
|     /* | 
|         Function: OnSearchFieldChange | 
|         Called when the content of the search field is changed. | 
|     */ | 
|     this.OnSearchFieldChange = function() | 
|         { | 
|         if (this.keyTimeout) | 
|             { | 
|             clearTimeout(this.keyTimeout); | 
|             this.keyTimeout = 0; | 
|             }; | 
|   | 
|         var searchValue = this.DOMSearchField().value.replace(/ +/g, ""); | 
|   | 
|         if (searchValue != this.lastSearchValue) | 
|             { | 
|             if (searchValue != "") | 
|                 { | 
|                 this.keyTimeout = setTimeout(this.name + ".Search()", this.keyTimeoutLength); | 
|                 } | 
|             else | 
|                 { | 
|                 if (this.mode == "HTML") | 
|                     {  this.DOMPopupSearchResultsWindow().style.display = "none";  }; | 
|                 this.lastSearchValue = ""; | 
|                 }; | 
|             }; | 
|         }; | 
|   | 
|   | 
|     /* | 
|         Function: OnSearchTypeFocus | 
|         Called when focus is added or removed from the search type. | 
|     */ | 
|     this.OnSearchTypeFocus = function(isActive) | 
|         { | 
|         this.Activate(isActive); | 
|         }; | 
|   | 
|   | 
|     /* | 
|         Function: OnSearchTypeChange | 
|         Called when the search type is changed. | 
|     */ | 
|     this.OnSearchTypeChange = function() | 
|         { | 
|         var searchValue = this.DOMSearchField().value.replace(/ +/g, ""); | 
|   | 
|         if (searchValue != "") | 
|             { | 
|             this.Search(); | 
|             }; | 
|         }; | 
|   | 
|   | 
|   | 
|     // Group: Action Functions | 
|     // ________________________________________________________________________ | 
|   | 
|   | 
|     /* | 
|         Function: CloseResultsWindow | 
|         Closes the results window. | 
|     */ | 
|     this.CloseResultsWindow = function() | 
|         { | 
|         this.DOMPopupSearchResultsWindow().style.display = "none"; | 
|         this.Activate(false, true); | 
|         }; | 
|   | 
|   | 
|     /* | 
|         Function: Search | 
|         Performs a search. | 
|     */ | 
|     this.Search = function() | 
|         { | 
|         this.keyTimeout = 0; | 
|   | 
|         var searchValue = this.DOMSearchField().value.replace(/^ +/, ""); | 
|         var searchTopic = this.DOMSearchType().value; | 
|   | 
|         var pageExtension = searchValue.substr(0,1); | 
|   | 
|         if (pageExtension.match(/^[a-z]/i)) | 
|             {  pageExtension = pageExtension.toUpperCase();  } | 
|         else if (pageExtension.match(/^[0-9]/)) | 
|             {  pageExtension = 'Numbers';  } | 
|         else | 
|             {  pageExtension = "Symbols";  }; | 
|   | 
|         var resultsPage; | 
|         var resultsPageWithSearch; | 
|         var hasResultsPage; | 
|   | 
|         // indexSectionsWithContent is defined in searchdata.js | 
|         if (indexSectionsWithContent[searchTopic][pageExtension] == true) | 
|             { | 
|             resultsPage = this.resultsPath + '/' + searchTopic + pageExtension + '.html'; | 
|             resultsPageWithSearch = resultsPage+'?'+escape(searchValue); | 
|             hasResultsPage = true; | 
|             } | 
|         else | 
|             { | 
|             resultsPage = this.resultsPath + '/NoResults.html'; | 
|             resultsPageWithSearch = resultsPage; | 
|             hasResultsPage = false; | 
|             }; | 
|   | 
|         var resultsFrame; | 
|         if (this.mode == "HTML") | 
|             {  resultsFrame = window.frames.MSearchResults;  } | 
|         else if (this.mode == "FramedHTML") | 
|             {  resultsFrame = window.top.frames['Content'];  }; | 
|   | 
|   | 
|         if (resultsPage != this.lastResultsPage || | 
|   | 
|             // Bug in IE.  If everything becomes hidden in a run, none of them will be able to be reshown in the next for some | 
|             // reason.  It counts the right number of results, and you can even read the display as "block" after setting it, but it | 
|             // just doesn't work in IE 6 or IE 7.  So if we're on the right page but the previous search had no results, reload the | 
|             // page anyway to get around the bug. | 
|             (browserType == "IE" && hasResultsPage && | 
|                 (!resultsFrame.searchResults || resultsFrame.searchResults.lastMatchCount == 0)) ) | 
|   | 
|             { | 
|             resultsFrame.location.href = resultsPageWithSearch; | 
|             } | 
|   | 
|         // So if the results page is right and there's no IE bug, reperform the search on the existing page.  We have to check if there | 
|         // are results because NoResults.html doesn't have any JavaScript, and it would be useless to do anything on that page even | 
|         // if it did. | 
|         else if (hasResultsPage) | 
|             { | 
|             // We need to check if this exists in case the frame is present but didn't finish loading. | 
|             if (resultsFrame.searchResults) | 
|                 {  resultsFrame.searchResults.Search(searchValue);  } | 
|   | 
|             // Otherwise just reload instead of waiting. | 
|             else | 
|                 {  resultsFrame.location.href = resultsPageWithSearch;  }; | 
|             }; | 
|   | 
|   | 
|         var domPopupSearchResultsWindow = this.DOMPopupSearchResultsWindow(); | 
|   | 
|         if (this.mode == "HTML" && domPopupSearchResultsWindow.style.display != "block") | 
|             { | 
|             var domSearchType = this.DOMSearchType(); | 
|   | 
|             var left = GetXPosition(domSearchType); | 
|             var top = GetYPosition(domSearchType) + domSearchType.offsetHeight; | 
|   | 
|             MoveToPosition(domPopupSearchResultsWindow, left, top); | 
|             domPopupSearchResultsWindow.style.display = 'block'; | 
|             }; | 
|   | 
|   | 
|         this.lastSearchValue = searchValue; | 
|         this.lastResultsPage = resultsPage; | 
|         }; | 
|   | 
|   | 
|   | 
|     // Group: Activation Functions | 
|     // Functions that handle whether the entire panel is active or not. | 
|     // ________________________________________________________________________ | 
|   | 
|   | 
|     /* | 
|         Function: Activate | 
|   | 
|         Activates or deactivates the search panel, resetting things to their default values if necessary.  You can call this on every | 
|         control's OnBlur() and it will handle not deactivating the entire panel when focus is just switching between them transparently. | 
|   | 
|         Parameters: | 
|   | 
|             isActive - Whether you're activating or deactivating the panel. | 
|             ignoreDeactivateDelay - Set if you're positive the action will deactivate the panel and thus want to skip the delay. | 
|     */ | 
|     this.Activate = function(isActive, ignoreDeactivateDelay) | 
|         { | 
|         // We want to ignore isActive being false while the results window is open. | 
|         if (isActive || (this.mode == "HTML" && this.DOMPopupSearchResultsWindow().style.display == "block")) | 
|             { | 
|             if (this.inactivateTimeout) | 
|                 { | 
|                 clearTimeout(this.inactivateTimeout); | 
|                 this.inactivateTimeout = 0; | 
|                 }; | 
|   | 
|             this.DOMSearchPanel().className = 'MSearchPanelActive'; | 
|   | 
|             var searchField = this.DOMSearchField(); | 
|   | 
|             if (searchField.value == 'Search') | 
|                  {  searchField.value = "";  } | 
|             } | 
|         else if (!ignoreDeactivateDelay) | 
|             { | 
|             this.inactivateTimeout = setTimeout(this.name + ".InactivateAfterTimeout()", this.inactivateTimeoutLength); | 
|             } | 
|         else | 
|             { | 
|             this.InactivateAfterTimeout(); | 
|             }; | 
|         }; | 
|   | 
|   | 
|     /* | 
|         Function: InactivateAfterTimeout | 
|   | 
|         Called by <inactivateTimeout>, which is set by <Activate()>.  Inactivation occurs on a timeout because a control may | 
|         receive OnBlur() when focus is really transferring to another control in the search panel.  In this case we don't want to | 
|         actually deactivate the panel because not only would that cause a visible flicker but it could also reset the search value. | 
|         So by doing it on a timeout instead, there's a short period where the second control's OnFocus() can cancel the deactivation. | 
|     */ | 
|     this.InactivateAfterTimeout = function() | 
|         { | 
|         this.inactivateTimeout = 0; | 
|   | 
|         this.DOMSearchPanel().className = 'MSearchPanelInactive'; | 
|         this.DOMSearchField().value = "Search"; | 
|   | 
|         this.lastSearchValue = ""; | 
|         this.lastResultsPage = ""; | 
|         }; | 
|     }; | 
|   | 
|   | 
|   | 
|   | 
| /* ________________________________________________________________________________________________________ | 
|   | 
|    Class: SearchResults | 
|    _________________________________________________________________________________________________________ | 
|   | 
|    The class that handles everything on the search results page. | 
|    _________________________________________________________________________________________________________ | 
| */ | 
|   | 
|   | 
| function SearchResults(name, mode) | 
|     { | 
|     /* | 
|         var: mode | 
|         The mode the search is going to work in, such as "HTML" or "FramedHTML". | 
|     */ | 
|     this.mode = mode; | 
|   | 
|     /* | 
|         var: lastMatchCount | 
|         The number of matches from the last run of <Search()>. | 
|     */ | 
|     this.lastMatchCount = 0; | 
|   | 
|   | 
|     /* | 
|         Function: Toggle | 
|         Toggles the visibility of the passed element ID. | 
|     */ | 
|     this.Toggle = function(id) | 
|         { | 
|         if (this.mode == "FramedHTML") | 
|             {  return;  }; | 
|   | 
|         var parentElement = document.getElementById(id); | 
|   | 
|         var element = parentElement.firstChild; | 
|   | 
|         while (element && element != parentElement) | 
|             { | 
|             if (element.nodeName == 'DIV' && element.className == 'ISubIndex') | 
|                 { | 
|                 if (element.style.display == 'block') | 
|                     {  element.style.display = "none";  } | 
|                 else | 
|                     {  element.style.display = 'block';  } | 
|                 }; | 
|   | 
|             if (element.nodeName == 'DIV' && element.hasChildNodes()) | 
|                 {  element = element.firstChild;  } | 
|             else if (element.nextSibling) | 
|                 {  element = element.nextSibling;  } | 
|             else | 
|                 { | 
|                 do | 
|                     { | 
|                     element = element.parentNode; | 
|                     } | 
|                 while (element && element != parentElement && !element.nextSibling); | 
|   | 
|                 if (element && element != parentElement) | 
|                     {  element = element.nextSibling;  }; | 
|                 }; | 
|             }; | 
|         }; | 
|   | 
|   | 
|     /* | 
|         Function: Search | 
|   | 
|         Searches for the passed string.  If there is no parameter, it takes it from the URL query. | 
|   | 
|         Always returns true, since other documents may try to call it and that may or may not be possible. | 
|     */ | 
|     this.Search = function(search) | 
|         { | 
|         if (!search) | 
|             { | 
|             search = window.location.search; | 
|             search = search.substring(1);  // Remove the leading ? | 
|             search = unescape(search); | 
|             }; | 
|   | 
|         search = search.replace(/^ +/, ""); | 
|         search = search.replace(/ +$/, ""); | 
|         search = search.toLowerCase(); | 
|   | 
|         if (search.match(/[^a-z0-9]/)) // Just a little speedup so it doesn't have to go through the below unnecessarily. | 
|             { | 
|             search = search.replace(/\_/g, "_und"); | 
|             search = search.replace(/\ +/gi, "_spc"); | 
|             search = search.replace(/\~/g, "_til"); | 
|             search = search.replace(/\!/g, "_exc"); | 
|             search = search.replace(/\@/g, "_att"); | 
|             search = search.replace(/\#/g, "_num"); | 
|             search = search.replace(/\$/g, "_dol"); | 
|             search = search.replace(/\%/g, "_pct"); | 
|             search = search.replace(/\^/g, "_car"); | 
|             search = search.replace(/\&/g, "_amp"); | 
|             search = search.replace(/\*/g, "_ast"); | 
|             search = search.replace(/\(/g, "_lpa"); | 
|             search = search.replace(/\)/g, "_rpa"); | 
|             search = search.replace(/\-/g, "_min"); | 
|             search = search.replace(/\+/g, "_plu"); | 
|             search = search.replace(/\=/g, "_equ"); | 
|             search = search.replace(/\{/g, "_lbc"); | 
|             search = search.replace(/\}/g, "_rbc"); | 
|             search = search.replace(/\[/g, "_lbk"); | 
|             search = search.replace(/\]/g, "_rbk"); | 
|             search = search.replace(/\:/g, "_col"); | 
|             search = search.replace(/\;/g, "_sco"); | 
|             search = search.replace(/\"/g, "_quo"); | 
|             search = search.replace(/\'/g, "_apo"); | 
|             search = search.replace(/\</g, "_lan"); | 
|             search = search.replace(/\>/g, "_ran"); | 
|             search = search.replace(/\,/g, "_com"); | 
|             search = search.replace(/\./g, "_per"); | 
|             search = search.replace(/\?/g, "_que"); | 
|             search = search.replace(/\//g, "_sla"); | 
|             search = search.replace(/[^a-z0-9\_]i/gi, "_zzz"); | 
|             }; | 
|   | 
|         var resultRows = document.getElementsByTagName("div"); | 
|         var matches = 0; | 
|   | 
|         var i = 0; | 
|         while (i < resultRows.length) | 
|             { | 
|             var row = resultRows.item(i); | 
|   | 
|             if (row.className == "SRResult") | 
|                 { | 
|                 var rowMatchName = row.id.toLowerCase(); | 
|                 rowMatchName = rowMatchName.replace(/^sr\d*_/, ''); | 
|   | 
|                 if (search.length <= rowMatchName.length && rowMatchName.substr(0, search.length) == search) | 
|                     { | 
|                     row.style.display = "block"; | 
|                     matches++; | 
|                     } | 
|                 else | 
|                     {  row.style.display = "none";  }; | 
|                 }; | 
|   | 
|             i++; | 
|             }; | 
|   | 
|         document.getElementById("Searching").style.display="none"; | 
|   | 
|         if (matches == 0) | 
|             {  document.getElementById("NoMatches").style.display="block";  } | 
|         else | 
|             {  document.getElementById("NoMatches").style.display="none";  } | 
|   | 
|         this.lastMatchCount = matches; | 
|   | 
|         return true; | 
|         }; | 
|     }; |