Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
12 lines
20 KiB
JavaScript
12 lines
20 KiB
JavaScript
/*
|
|
This file is part of Natural Docs, which is Copyright © 2003-2022 Code Clear LLC.
|
|
Natural Docs is licensed under version 3 of the GNU Affero General Public
|
|
License (AGPL). Refer to License.txt or www.naturaldocs.org for the
|
|
complete details.
|
|
|
|
This file may be distributed with documentation files generated by Natural Docs.
|
|
Such documentation is not covered by Natural Docs' copyright and licensing,
|
|
and may have its own copyright and distribution terms as decided by its author.
|
|
*/
|
|
|
|
"use strict";var NDSearch=new function(){this.Start=function(){this.domSearchField=document.getElementById("NDSearchField");this.domResults=document.createElement("div");this.domResults.id="NDSearchResults";this.domResults.style.display="none";this.domResults.style.position="fixed";this.domResultsContent=document.createElement("div");this.domResultsContent.id="SeContent";this.domResults.appendChild(this.domResultsContent);document.body.appendChild(this.domResults);this.initialTimeoutStatus=1;this.topLevelEntryCount=0;this.visibleEntryCount=0;this.openParents=[];this.keyboardSelectionIndex=-1;this.moreResultsThreshold=25;this.allPrefixesStatus=1;this.prefixObjects={};this.domSearchField.onfocus=function(){NDSearch.OnSearchFieldFocus();};this.domSearchField.onkeydown=function(event){NDSearch.OnSearchFieldKey(event);};this.domSearchField.oninput=function(event){NDSearch.OnSearchFieldChange(event);};this.domResults.onfocus=function(){NDSearch.OnResultsFocus();};this.DeactivateSearchField();};this.Update=function(){if(!this.SearchFieldIsActive()){return;}var searchInterpretations=this.GetSearchInterpretations();if(searchInterpretations.length==0){this.ClearResults();return;}if(this.allPrefixesStatus!=3){this.ClearResults(true);this.domResultsContent.innerHTML=this.BuildSearchingStatus();this.ShowResults();return;}var searchInterpretationPrefixes=this.GetMatchingPrefixes(searchInterpretations);this.RemoveUnusedPrefixObjects(searchInterpretationPrefixes);if(searchInterpretationPrefixes.length==0){this.ClearResults(true);this.domResultsContent.innerHTML=this.BuildNoMatchesStatus();this.ShowResults();return;}var location=new NDLocation(window.location.hash);var favorClasses=(location.type!="File");var forceExpansion=(this.TotalMatchesGreaterThan(searchInterpretations,searchInterpretationPrefixes,10)===false);var buildResults=this.BuildResults(searchInterpretations,searchInterpretationPrefixes,favorClasses,forceExpansion);var oldScrollTop=this.domResults.scrollTop;this.domResultsContent.innerHTML=buildResults.html;this.ShowResults();this.domResults.scrollTop=oldScrollTop;if(this.keyboardSelectionIndex!=-1){var domSelectedEntry=document.getElementById("SeSelectedEntry");if(domSelectedEntry!=undefined){this.ScrollEntryIntoView(domSelectedEntry,false);}}if(buildResults.prefixDataToLoad!=undefined){this.LoadPrefixData(buildResults.prefixDataToLoad);}};this.ClearResults=function(internalOnly){if(this.updateTimeout!=undefined){clearTimeout(this.updateTimeout);this.updateTimeout=undefined;}if(this.initialTimeout!=undefined){clearTimeout(this.initialTimeout);this.initialTimeout=undefined;}this.initialTimeoutStatus=1;if(!internalOnly){this.HideResults();}this.visibleEntryCount=0;this.topLevelEntryCount=0;this.openParents=[];this.keyboardSelectionIndex=-1;this.moreResultsThreshold=25;this.prefixObjects={};};this.ToggleParent=function(topLevelIndex,fromKeyboard){var openParentsIndex=this.openParents.indexOf(topLevelIndex);var opening=(openParentsIndex==-1);if(opening){this.openParents.push(topLevelIndex);}else{this.openParents.splice(openParentsIndex,1);}if(!fromKeyboard){this.keyboardSelectionIndex=-1;this.domSearchField.focus();}this.Update();if(opening){var children=this.domResultsContent.children;var topLevelCount=0;var domToggledElement=undefined;for(var i=0;i<children.length;i++){if(NDCore.HasClass(children[i],"SeEntry")){if(topLevelCount==topLevelIndex){domToggledElement=children[i];break;}else{topLevelCount++;}}}if(domToggledElement!=undefined){this.ScrollEntryIntoView(domToggledElement,true);}}if(navigator.userAgent.indexOf("KHTML")!=-1&&this.domResults.scrollTop>0){this.domResults.scrollTop--;}};this.LoadMoreResults=function(){this.moreResultsThreshold=this.visibleEntryCount+25;this.domSearchField.focus();this.Update();};this.ActivateLinkFromKeyboard=function(domLink){var address=domLink.getAttribute("href");if(address.substr(0,11)=="javascript:"){address=address.substr(11);address=address.replace(/^(NDSearch.ToggleParent\([0-9]+,)false(.*)$/,"$1true$2");eval(address);}else{location.href=address;}};this.OnSearchFieldFocus=function(){if(!this.SearchFieldIsActive()){this.ActivateSearchField();if(this.allPrefixesStatus==1){this.allPrefixesStatus=2;NDCore.LoadJavaScript("search/index.js");}}};this.OnSearchFieldKey=function(event){if(event===undefined){event=window.event;}if(event.keyCode==27){this.ClearResults();this.DeactivateSearchField();this.domSearchField.blur();document.getElementById("CFrame").contentWindow.focus();}else if(event.keyCode==38){if(this.keyboardSelectionIndex<=0){this.keyboardSelectionIndex=this.visibleEntryCount-1;}else{this.keyboardSelectionIndex--;}this.UpdateSelection();}else if(event.keyCode==40){if(this.visibleEntryCount==0){this.keyboardSelectionIndex=-1;}else if(this.keyboardSelectionIndex>=this.visibleEntryCount-1){this.keyboardSelectionIndex=0;}else{this.keyboardSelectionIndex++;}this.UpdateSelection();}else if(event.keyCode==37){if(this.keyboardSelectionIndex!=-1){var domSelectedEntry=document.getElementById("SeSelectedEntry");if(NDCore.HasClass(domSelectedEntry,"SeParent")&&NDCore.HasClass(domSelectedEntry,"open")){this.ActivateLinkFromKeyboard(domSelectedEntry);}}}else if(event.keyCode==39){if(this.keyboardSelectionIndex!=-1){var domSelectedEntry=document.getElementById("SeSelectedEntry");if(NDCore.HasClass(domSelectedEntry,"SeParent")&&NDCore.HasClass(domSelectedEntry,"closed")){this.ActivateLinkFromKeyboard(domSelectedEntry);}}}else if(event.keyCode==13){var domSelectedEntry=undefined;if(this.keyboardSelectionIndex!=-1){domSelectedEntry=document.getElementById("SeSelectedEntry");}else if(this.visibleEntryCount==1){domSelectedEntry=this.domResultsContent.firstChild;}else if(this.visibleEntryCount==2&&NDCore.HasClass(this.domResultsContent.firstChild,"SeParent")){domSelectedEntry=this.domResultsContent.childNodes[1].firstChild;}if(domSelectedEntry!=undefined){this.ActivateLinkFromKeyboard(domSelectedEntry);}else if(this.keyboardSelectionIndex==-1&&this.visibleEntryCount>0){this.keyboardSelectionIndex=0;this.UpdateSelection();}}};this.OnSearchFieldChange=function(event){if(event===undefined){event=window.event;}this.keyboardSelectionIndex=-1;if(this.initialTimeoutStatus==3){if(this.updateTimeout==undefined){this.updateTimeout=setTimeout(function(){clearTimeout(NDSearch.updateTimeout);NDSearch.updateTimeout=undefined;NDSearch.Update();},350);}}else{var searchInterpretations=this.GetSearchInterpretations();if(searchInterpretations.length!=0&&this.allPrefixesStatus==3&&this.GetMatchingPrefixes(searchInterpretations).length<=1){if(this.initialTimeoutStatus==2){clearTimeout(this.initialTimeout);this.initialTimeout=undefined;}this.initialTimeoutStatus=3;this.Update();}else if(this.initialTimeoutStatus==1){this.initialTimeoutStatus=2;this.initialTimeout=setTimeout(function(){if(NDSearch.initialTimeoutStatus==2){clearTimeout(NDSearch.initialTimeout);NDSearch.initialTimeout=undefined;NDSearch.initialTimeoutStatus=3;NDSearch.Update();}},1250);}}};this.OnResultsFocus=function(){this.domSearchField.focus();};this.OnUpdateLayout=function(){if(this.domResults!=undefined){this.PositionResults();if(this.keyboardSelectionIndex!=-1){var domSelectedEntry=document.getElementById("SeSelectedEntry");if(domSelectedEntry!=undefined){this.ScrollEntryIntoView(domSelectedEntry,false);}}}};this.GetSearchInterpretations=function(){var interpretations=[];var normalizedSearchText=this.domSearchField.value.toLowerCase();normalizedSearchText=normalizedSearchText.replace(/\s+/g," ");normalizedSearchText=normalizedSearchText.replace(/^ /,"");normalizedSearchText=normalizedSearchText.replace(/ $/,"");normalizedSearchText=normalizedSearchText.replace(/([^a-z0-9_]) /g,"$1");normalizedSearchText=normalizedSearchText.replace(/ (?=[^a-z0-9_])/g,"");normalizedSearchText=normalizedSearchText.replace(/::|->/g,".");normalizedSearchText=normalizedSearchText.replace(/\\/g,"/");normalizedSearchText=normalizedSearchText.replace(/^[./]+/,"");if(normalizedSearchText==""){return interpretations;}interpretations.push(normalizedSearchText);var lastChar=normalizedSearchText.charAt(normalizedSearchText.length-1);if(lastChar==":"||lastChar=="-"){interpretations.push(normalizedSearchText.substr(0,normalizedSearchText.length-1)+".");}return interpretations;};this.GetMatchingPrefixes=function(searchTextArray){var matchingPrefixes=[];if(this.allPrefixesStatus!=3){return matchingPrefixes;}for(var i=0;i<searchTextArray.length;i++){var searchText=searchTextArray[i];var searchPrefix=this.MakePrefix(searchText);if(searchPrefix!=undefined&&searchPrefix!=""){var prefixIndex=this.GetAllPrefixesIndex(searchPrefix);while(prefixIndex<this.allPrefixes.length){if(this.allPrefixes[prefixIndex].length>=searchPrefix.length&&this.allPrefixes[prefixIndex].substr(0,searchPrefix.length)==searchPrefix){matchingPrefixes.push(this.allPrefixes[prefixIndex]);prefixIndex++;}else{break;}}}}if(searchTextArray.length<=1){return matchingPrefixes;}matchingPrefixes.sort();for(var i=1;i<matchingPrefixes.length;){if(matchingPrefixes[i]==matchingPrefixes[i-1]){matchingPrefixes.splice(i,1);}else{i++;}}return matchingPrefixes;};this.GetAllPrefixesIndex=function(prefix){if(this.allPrefixesStatus!=3){return undefined;}if(this.allPrefixes.length==0){return 0;}var firstIndex=0;var lastIndex=this.allPrefixes.length-1;for(;;){var testIndex=(firstIndex+lastIndex)>>1;if(prefix==this.allPrefixes[testIndex]){return testIndex;}else if(prefix<this.allPrefixes[testIndex]){if(testIndex==firstIndex){return testIndex;}else{lastIndex=testIndex;}}else{if(testIndex==lastIndex){return lastIndex+1;}else{firstIndex=testIndex+1;}}}};this.KeywordMatchesInterpretations=function(keywordObject,interpretations){for(var i=0;i<interpretations.length;i++){var interpretation=interpretations[i];if(interpretation.length<=keywordObject[1].length){if(keywordObject[1].indexOf(interpretation)!=-1){return true;}}else{if(interpretation.indexOf(keywordObject[1])!=-1){return true;}}}return false;};this.MemberMatchesInterpretations=function(memberObject,interpretations){for(var i=0;i<interpretations.length;i++){var interpretation=interpretations[i];if(memberObject[3].indexOf(interpretation)!=-1){return true;}}return false;};this.TotalMatchesGreaterThan=function(searchInterpretations,searchInterpretationPrefixes,maximum){var totalMatches=0;for(var p=0;p<searchInterpretationPrefixes.length;p++){var prefix=searchInterpretationPrefixes[p];if(this.prefixObjects[prefix]==undefined||this.prefixObjects[prefix][2]==false){return undefined;}var keywordObjects=this.prefixObjects[prefix][1];for(var k=0;k<keywordObjects.length;k++){var keywordObject=keywordObjects[k];if(this.KeywordMatchesInterpretations(keywordObject,searchInterpretations)){var memberObjects=keywordObject[2];for(var m=0;m<memberObjects.length;m++){var memberObject=memberObjects[m];if(this.MemberMatchesInterpretations(memberObject,searchInterpretations)){totalMatches++;if(totalMatches>maximum){return true;}}}}}}return false;};this.BuildResults=function(searchInterpretations,searchInterpretationPrefixes,favorClasses,forceExpansion){var results={html:""};this.topLevelEntryCount=0;this.visibleEntryCount=0;var addSearchingStatus=false;for(var p=0;p<searchInterpretationPrefixes.length;p++){var prefix=searchInterpretationPrefixes[p];if(this.prefixObjects[prefix]==undefined){if(this.visibleEntryCount<this.moreResultsThreshold){results.prefixDataToLoad=prefix;addSearchingStatus=true;}else{results.html+=this.BuildMoreResultsEntry();}break;}else if(this.prefixObjects[prefix][2]==false){addSearchingStatus=true;break;}var keywordObjects=this.prefixObjects[prefix][1];for(var k=0;k<keywordObjects.length;k++){results.html+=this.BuildKeyword(keywordObjects[k],searchInterpretations,favorClasses,forceExpansion);}}if(addSearchingStatus){results.html+=this.BuildSearchingStatus();}else if(results.html==""){results.html+=this.BuildNoMatchesStatus();}return results;};this.BuildKeyword=function(keywordObject,searchInterpretations,favorClasses,forceExpansion){if(this.KeywordMatchesInterpretations(keywordObject,searchInterpretations)==false){return"";}var memberMatches=0;var lastMatchingMemberObject;for(var i=0;i<keywordObject[2].length;i++){var memberObject=keywordObject[2][i];if(this.MemberMatchesInterpretations(memberObject,searchInterpretations)){lastMatchingMemberObject=memberObject;memberMatches++;}}if(memberMatches==0){return"";}else if(memberMatches==1&&lastMatchingMemberObject[3]==keywordObject[1]){var selected=(this.keyboardSelectionIndex==this.visibleEntryCount);var commentType=lastMatchingMemberObject[4];var target;if(favorClasses&&lastMatchingMemberObject[6]!=undefined){target=lastMatchingMemberObject[6];}else{target=lastMatchingMemberObject[5];}var html="<a class=\"SeEntry T"+commentType+"\" "+(selected?"id=\"SeSelectedEntry\" ":"")+"href=\"#"+target+"\">"+"<div class=\"SeEntryIcon\"></div>"+lastMatchingMemberObject[1];if(lastMatchingMemberObject[0]!=undefined||lastMatchingMemberObject[2]!=undefined){html+="<span class=\"SeQualifier\">";if(lastMatchingMemberObject[0]!=undefined){html+=", "+lastMatchingMemberObject[0];}if(lastMatchingMemberObject[2]!=undefined){html+=", "+lastMatchingMemberObject[2];}html+="</span>";}html+="</a>";this.topLevelEntryCount++;this.visibleEntryCount++;return html;}else{var selected=(this.keyboardSelectionIndex==this.visibleEntryCount);var openClosed;if(forceExpansion||this.openParents.indexOf(this.topLevelEntryCount)!=-1){openClosed="open";}else{openClosed="closed";}var html="<a class=\"SeEntry SeParent "+openClosed+"\" "+(selected?"id=\"SeSelectedEntry\" ":"")+"href=\"javascript:NDSearch.ToggleParent("+this.topLevelEntryCount+",false)\">"+"<div class=\"SeEntryIcon\"></div>"+keywordObject[0]+" <span class=\"SeChildCount\">("+memberMatches+")</span>"+"</a>";this.topLevelEntryCount++;this.visibleEntryCount++;if(openClosed=="open"){html+="<div class=\"SeChildren\">";for(var i=0;i<keywordObject[2].length;i++){var memberObject=keywordObject[2][i];if(this.MemberMatchesInterpretations(memberObject,searchInterpretations)){var selected=(this.keyboardSelectionIndex==this.visibleEntryCount);var commentType=memberObject[4];var target;if(favorClasses&&memberObject[6]!=undefined){target=memberObject[6];}else{target=memberObject[5];}html+="<a class=\"SeEntry T"+commentType+"\" "+(selected?"id=\"SeSelectedEntry\" ":"")+"href=\"#"+target+"\">"+"<div class=\"SeEntryIcon\"></div>"+memberObject[1];if(memberObject[0]!=undefined||memberObject[2]!=undefined){html+="<span class=\"SeQualifier\">";if(memberObject[0]!=undefined){html+=", "+memberObject[0];}if(memberObject[2]!=undefined){html+=", "+memberObject[2];}html+="</span>";}html+="</a>";this.visibleEntryCount++;}}html+="</div>";}return html;}};this.BuildSearchingStatus=function(){return"<div class=\"SeStatus Searching\">"+"Searching..."+"</div>";};this.BuildNoMatchesStatus=function(){return"<div class=\"SeStatus NoResults\">"+"No Matches"+"</div>";};this.BuildMoreResultsEntry=function(){var selected=(this.keyboardSelectionIndex==this.visibleEntryCount);var html="<a class=\"SeEntry MoreResults\" "+(selected?"id=\"SeSelectedEntry\" ":"")+"href=\"javascript:NDSearch.LoadMoreResults();\">"+"<div class=\"SeEntryIcon\"></div>"+"More Results..."+"</a>";this.visibleEntryCount++;this.topLevelEntryCount++;return html;};this.MakePrefix=function(searchText){var prefix="";for(var i=0;i<3;i++){if(i>=searchText.length){break;}var char=searchText.charAt(i);if(char==" "||char=="."||char=="/"){break;}prefix+=char;}if(prefix.length>0){return prefix;}else{return undefined;}};this.PrefixToHex=function(prefix){var hex="";for(var i=0;i<prefix.length;i++){var charValue="0000"+prefix.charCodeAt(i).toString(16);hex+=charValue.substr(charValue.length-4,4);}return hex;};this.PrefixToDataFile=function(prefix){return"search/keywords/"+this.PrefixToHex(prefix)+".js";};this.ActivateSearchField=function(){this.domSearchField.value="";NDCore.RemoveClass(this.domSearchField,"DefaultText");};this.DeactivateSearchField=function(){NDCore.AddClass(this.domSearchField,"DefaultText");this.domSearchField.value="Search";};this.SearchFieldIsActive=function(){return(NDCore.HasClass(this.domSearchField,"DefaultText")==false);};this.ShowResults=function(){this.domResults.style.display="block";this.PositionResults();};this.HideResults=function(){this.domResults.style.display="none";};this.PositionResults=function(){this.domResults.style.visibility="hidden";var oldScrollTop=this.domResults.scrollTop;this.domResults.style.left="0px";this.domResults.style.top="0px";this.domResults.style.width="auto";this.domResults.style.height="auto";var urX=this.domSearchField.offsetLeft+this.domSearchField.offsetWidth;var urY=this.domSearchField.offsetTop+this.domSearchField.offsetHeight+5;var maxWidth=urX-25;var maxHeight=window.innerHeight-urY-25;if(this.domResults.offsetHeight>maxHeight){this.domResults.style.height=maxHeight+"px";}if(this.domResults.offsetWidth>maxWidth){this.domResults.style.width=maxWidth+"px";}else if(this.domResults.offsetWidth<this.domSearchField.offsetWidth){this.domResults.style.width=this.domSearchField.offsetWidth+"px";}else{this.domResults.style.width=(this.domResults.offsetWidth+1)+"px";}this.domResults.style.left=(urX-this.domResults.offsetWidth)+"px";this.domResults.style.top=urY+"px";this.domResults.scrollTop=oldScrollTop;this.domResults.style.visibility="visible";};this.UpdateSelection=function(){var domCurrentSelection=document.getElementById("SeSelectedEntry");var domNewSelection=undefined;if(this.keyboardSelectionIndex!=-1){domNewSelection=this.domResultsContent.getElementsByClassName("SeEntry")[this.keyboardSelectionIndex];}if(domCurrentSelection!=undefined){domCurrentSelection.id=undefined;}if(domNewSelection!=undefined){domNewSelection.id="SeSelectedEntry";this.ScrollEntryIntoView(domNewSelection,false);}};this.ScrollEntryIntoView=function(domEntry,includeChildren){var itemTop=domEntry.offsetTop;var itemBottom;if(includeChildren&&NDCore.HasClass(domEntry,"open")){var domSelectedChildren=domEntry.nextSibling;itemBottom=domSelectedChildren.offsetTop+domSelectedChildren.offsetHeight;}else{itemBottom=itemTop+domEntry.offsetHeight;}var windowTop=this.domResults.scrollTop;var windowBottom=windowTop+this.domResults.clientHeight;var offset=0;if(windowBottom<itemBottom){offset=itemBottom-windowBottom;}if(windowTop+offset>itemTop){offset=itemTop-windowTop;}if(offset!=0){this.domResults.scrollTop+=offset;}};this.OnPrefixIndexLoaded=function(prefixes){this.allPrefixes=prefixes;this.allPrefixesStatus=3;if(this.initialTimeoutStatus==3){this.Update();}};this.LoadPrefixData=function(prefix){if(this.prefixObjects[prefix]==undefined){var prefixObject=[];prefixObject[0]=prefix;prefixObject[2]=false;prefixObject[3]="NDPrefixLoader_"+this.PrefixToHex(prefix);this.prefixObjects[prefix]=prefixObject;NDCore.LoadJavaScript(this.PrefixToDataFile(prefix),prefixObject[3]);}};this.OnPrefixDataLoaded=function(prefix,commentTypes,keywordObjects){var prefixObject=this.prefixObjects[prefix];if(prefixObject==undefined){return;}for(var k=0;k<keywordObjects.length;k++){var keywordObject=keywordObjects[k];if(keywordObject[1]==undefined){keywordObject[1]=keywordObject[0].toLowerCase();}for(var m=0;m<keywordObject[2].length;m++){var memberObject=keywordObject[2][m];var commentTypeIndex=memberObject[4];memberObject[4]=commentTypes[commentTypeIndex];if(memberObject[1]==undefined){memberObject[1]=keywordObject[0];}if(memberObject[3]==undefined){memberObject[3]=memberObject[1].toLowerCase();}}}prefixObject[1]=keywordObjects;prefixObject[2]=true;NDCore.RemoveScriptElement(prefixObject[3]);this.Update();};this.RemoveUnusedPrefixObjects=function(usedPrefixes){if(usedPrefixes.length==0){this.prefixObjects={};return;}for(var prefix in this.prefixObjects){if(usedPrefixes.indexOf(prefix)==-1){this.prefixObjects[prefix]=undefined;}}};}; |