Skip to main content

How to Make a Personal Question and Answer Search Engine in HTML & Javascript

I started making games and other programs in JavaScript because it is easy to add the code to websites.

Personal Question and Answer Search Engine

Search engines are great for finding lots of useful information, but they often provide you with too much information. It can take time to sort through it to find what you need. Most people end up doing the same search over again because they don't remember everything. I started adding useful information to a file so it would be easy to find but it became harder and harder to find what I was looking for.

A personal question and answer search engine makes it easier to find what you are looking for. Type a question. If the answer you want is not there find it. Then add it so it will be there next time. I made a simple question and answer search engine because I don't have a photographic memory. Computers don't forget. They can remember everything you add to them and my computer program makes it easy to find the information I am looking for.

If you don't remember everything then get your computer to remember for you.


Knowledge Base

A knowledge base is a collection of knowledge stored in a file. They can be used to store many bits of useful information, including answers to frequently asked questions. While taking notes you may type or paste information into a text editor like Notepad or Wordpad. For this program you ask a question then you add the answer to a text box. Instead of just taking notes you are adding content to the search engine so it is easier to find.

After adding some recipes to a knowledge base, I could type 'How to make chicken and rice?' and it would give me the recipe. Using my JavaScript and HTML knowledge base I could ask "How to save and load data to local storage?" and it would give me code that I could copy and paste into an HTML page.


Ideas for a Knowledge Base

computer code

general knowledge

how to

expert systems



AI computer players

facts and trivia

technical questions

chat bot

frequently asked questions


game bot



virtual you

help center


HTML Page with Buttons

<!DOCTYPE html>
<meta charset="utf-8">
<meta content="keyword1,keyword2,keyword3,etc." name="keywords">
<meta content="A short description." name="description">
<title>Title of the Page</title>
<body onload="OnLoad()">
<a style="font-weight:bold;font-size: 120%;">Personal Question & Answer Search Engine</a> <input id="KBName" type="text" placeholder="Name of Knowledge Base">
<div class="autocomplete" id="autocomplete" style="width:300px;">
   <input id="myQuestion" type="text" name="myQuestion" placeholder="Question">
<br><br><br><textarea style="width:100%;height:50px;border-width: 0;" id="text1" placeholder="Answer will appear here."></textarea>
<button onclick="SetAnswer()">Answer</button> <button onclick="RemoveQuestion()">Remove Question</button> <button onclick="RemoveQuestions()">Clear questions.</button> &nbsp <button id="Backup">Backup</button> <a download="MyQnAFile.txt" id="downloadlink" style="display: none;">Download</a> <button style="display:initial;" onclick="document.getElementById('getFile').click()">Restore</button>
<textarea id="Text2" style="display:none;">Used while sending data to text file.</textarea>
<input type='file' id="getFile" style="display:none;" accept='text/plain' onchange='openFile(event)'>

//Put the JavaScript below between the script tags.



Autocomplete gives the user the option of completing words or sentences. You need it so you can match new questions with ones that have already been asked. It saves time and shows the user a list of similar question that have already been asked. The autocomplete function is the main function. If I start typing "How to" it would give me a list of questions that contain the words "how to".

var KBName=document.getElementById("KBName");
var myQuestion=document.getElementById("myQuestion"); //input for Questions
var Text1=document.getElementById("text1");    //TextBox for showing answers
var Text2 = document.getElementById('Text2'); //textbox for saving to text file
var Complete=document.getElementById("autocomplete"); //div
var Backup = document.getElementById('Backup'); //button

var QuestionL=[],AnswerL=[],OnQuestion=-1;
var ScreenRatio=Math.ceil(window.devicePixelRatio);
var ScreenHeight=Math.floor(window.innerHeight*ScreenRatio-6*ScreenRatio);
var ScreenWidth=Math.floor(window.innerWidth*ScreenRatio);*.98)+"px";; = "600px";; = "600px";

myQuestion.focus();*.5+"px"; = "fixed";

var input = myQuestion;
input.addEventListener("keyup", function(event) { event.preventDefault(); if (event.keyCode === 13) AddNewQuestion(); });

function autocomplete(TxtInp, AutoLst,Lst2)  //(input object,array,array)
   var BestMatch=0,Matches=[];
   TxtInp.addEventListener("input", function(e) { //Runs when user writes in the text field.

      var Div1, Div2, val = this.value;

      closeAllLists(); //close open lists
      if (!val) { Text1.placeholder="Answer will appear here.";return false;}
      Text1.placeholder=""; //so do not see placeholder under auto complete text
      Div1 = document.createElement("DIV"); //create Div to contain values
      Div1.setAttribute("id", + "autocomplete-list");
      Div1.setAttribute("class", "autocomplete-items");      
      this.parentNode.appendChild(Div1); //add DIV child of autocomplete element

      var Srt=SortMatches(AutoLst,Lst2,val);


      for (var i = 0; i < AutoLst.length; i++) {       //main loop
         //step 1. break AutoLst[i] & val into words
         var Q=AutoLst[i]; //Q from questions list, U users question
         var Q2="",U=val,U2="",Max=15;

         for(var loo=0;loo<Q.length-1;loo++) {Q2=Q2+Q[loo];} 
         Q2 = Q2.replace(/,/g, ", ");Q2 = Q2.replace(/ +/g, " "); //make sure space after comma & remove extra spaces
         Q3 = Q2.replace(/,/g, "");  //remove commas from Q3
         var Qwords = Q3.split(" "); //turn sentence into array of words
         var Qwords2 = Q2.split(" "); //turn sentence into array of words

         for(var loo=0;loo<U.length;loo++) if(U[loo]!="?" & U[loo]!=".") {U2=U2+U[loo].toLowerCase()}
         U3 = U2.replace(/,/g, " ");U3 = U3.replace(/ +/g, " "); //remove commas & extra spaces
         var Uwords = U3.split(" ");  //Seperate users sentence into words

         for(var j=0;j<Uwords.length;j++) Uwords[j]=Uwords[j].toLowerCase();
         MatchCount=Matches[i]; //values from sorting       

         if (MatchCount>0 & i<Max) {  //could use  MatchCount==BestMatch
            Div2 = document.createElement("DIV");             //Make Div element for each match
            for(var L=0;L<Qwords.length;L++) // make matching words bold 
               if(Uwords.indexOf(Qwords[L].toLowerCase())>-1) if(L<Qwords.length-1) { if( Qwords2[L].indexOf(",")==-1) { Div2.innerHTML+="<strong>"+Qwords2[L]+" </strong>"; } else Div2.innerHTML+="<strong>"+Qwords2[L].substring(0, Qwords2[L].length-1)+"</strong>, ";  } else {Div2.innerHTML+="<strong>"+Qwords2[L]+"</strong>?";}
               else if(L<Qwords.length-1) {Div2.innerHTML+=Qwords2[L]+" ";} else Div2.innerHTML+=Qwords2[L]+"?";

            Div2.innerHTML += "<input type='hidden' value='" + AutoLst[i] + "'>"; //holds current array's value
            Div2.addEventListener("click", function(e) { //run when Div element is clicked
              TxtInp.value = this.getElementsByTagName("input")[0].value;   
              closeAllLists(); //close  autocomplete values,
            Div1.appendChild(Div2); //adds div2 to Div1
      } //end of loop
   }); //end of TxtInp.addEventListener

  TxtInp.addEventListener("keydown", function(e) {
     //could add arrow keys
      if(e.keyCode == 13) { //enter key

  function closeAllLists(elmnt) { 
    var ACI = document.getElementsByClassName("autocomplete-items"); //close autocomplete lists
    for (var i = 0; i < ACI.length; i++) ACI[i].parentNode.removeChild(ACI[i]); 
  document.addEventListener("click", function (e) { //when click on page.

Functions autocomplete needs

function SortMatches(AutoLst,Lst2,val)
   var BestMatch=0,Matches=[],Srt=[];
   //Count number of matches   
   for(var i=0;i<AutoLst.length;i++) //loop through all the possible questions
   {  //Q from question list, U from user's question
      var Q=AutoLst[i],Q2="",U=val,U2="";

      Q2 = Q.replace(/\?/g,""); //remove ?
      Q2 = Q2.replace(/,/g," "); //replace commas with space.
      Q2 = Q2.replace(/ +/g, " "); //remove double spaces
      var Qwords = Q2.split(" "); //turn string into an array

      U2 = U.replace(/\?|\./g," "); // replace ? & . Need \ before speicial characters
      U2 = U2.replace(/,/g," "); // replace commas
      U2 = U2.replace(/ +/g, " "); //remove double spaces
      if(U2[U2.length-1]==" " & i==0) { U2=U2.slice(0, -1);} //if last is space remove it
      var Uwords = U2.split(" ");

      for(var j=0;j<Uwords.length;j++)
         for(var loo=0;loo<Qwords.length;loo++) if(Uwords[j].toUpperCase()==Qwords[loo].toUpperCase()) {Matches[i]++;break;}      
   } //end of i loop

   //Sort according to Matches
   for(var j=0;j<AutoLst.length-1;j++) //loop through all question words
      for(var i=0;i<AutoLst.length-1;i++) //loop through words user entered
         if(Matches[i]>BestMatch) BestMatch=Matches[i];
            var AutoLstT=AutoLst[i];AutoLst[i]=AutoLst[i+1];AutoLst[i+1]=AutoLstT; //switch questions
            var Lst2T=Lst2[i];Lst2[i]=Lst2[i+1];Lst2[i+1]=Lst2T;   //switch answers
            var MatchesT=Matches[i];Matches[i]=Matches[i+1];Matches[i+1]=MatchesT; //switch matches
   return Srt;

function LowerArray() //make Question Array all lower case
  var LowerQuestions=[];
  for(var i=0;i<QuestionL.length;i++) LowerQuestions[i]=QuestionL[i].toLowerCase();
  return LowerQuestions; 

function FilterQuestion(TempValue,Mark) //pass value when not using Question input, Mark true to add Question mark
  var CanChange=false;
  if(TempValue==undefined || TempValue==null) {TempValue=myQuestion.value;CanChange=true;}
  var value=""
  TempValue = TempValue.replace(/ +/g, " "); //replace double spaces with single spaces
  if(TempValue.length==0) {return value;}

  for(var i=0;i<TempValue.length;i++) if(TempValue[i]!="." & TempValue[i]!=":" & TempValue[i]!=";") value=value+TempValue[i]; 
  if(value[value.length-1]!="?" & Mark!=false) {value=value+"?";}

   value = value.replace(/ \?/g,"?"); //handle blank space at end of question

  if(value.length>0) value=value[0].toUpperCase()+value.substring(1, value.length); //make sure 1st letter of question is capitalized
  if(CanChange & value.length>5) { myQuestion.value=value; } //change question asked to match filter

  return value;

function FilterAllQuestions() {  for(var i=0;i<QuestionL.length;i++) QuestionL[i]=FilterQuestion(QuestionL[i]); }

function AddNewQuestion(K)
  var value=FilterQuestion();if(value.length<6)  {return;}
  FilterAllQuestions(); //double check to make sure questions asked match new question format
  OnQuestion= FindQ()
  if(OnQuestion>-1) GetAnswer(); //Asked before
  else {OnQuestion=QuestionL.length;QuestionL[QuestionL.length]=value;AnswerL[AnswerL.length]="";if(K!=true) Text1.value="";if(K!=true) SaveQuestions("AddNewQuestion"); } //new

function GetAnswer() //display answer to the question if there is one
  if(OnQuestion>-1) { if(AnswerL[OnQuestion]==undefined || AnswerL[OnQuestion]==null) AnswerL[OnQuestion]=""; Text1.value=AnswerL[OnQuestion];}
  else {Text1.value="";OnQuestion=QuestionL.length; AddNewQuestion(); }

function FindQ(Q) //look for index of question
   var CanChange=false;
   if(Q==undefined) {Q=myQuestion.value;CanChange=true;}
   if(CanChange) myQuestion.value=Q;
   var InputLower=Q.toLowerCase();
   var LowerQuestions=LowerArray(QuestionL);
   var index=LowerQuestions.indexOf(InputLower);
   return index;

function SetAnswer() //when user answers a question
  if(myQuestion.value.length<6) return; //return if question length is too short
  if(OnQuestion<0) AddNewQuestion(true);
  else {var value=FilterQuestion(); QuestionL[OnQuestion]=value;AnswerL[OnQuestion]=Text1.value;SaveQuestions("SetAnswer");}

Saving the Knowledge

When you ask and answer questions the information is saved automatically using 'localStorage'. It stores the information for the current knowledge base on your computer. Only the current browser can access it. So if you made the knowledge base in Chrome you can't access it in Firefox. You can also save and load using text files. Saving and loading text files is done manually with the 'Backup' and 'Restore' buttons.

A knowledge base that is saved to a text file can be accessed by different browsers. You could even e-mail it to someone that has this program on their computer.

Save & Load Local

function SaveQuestions(Where)
   for(var i=0;i<AnswerL.length;i++) if(AnswerL[i]==undefined) {AnswerL[i]="";alert("Found undefined");}  //make sure no undefined answers
   FilterAllQuestions(); //make sure Question has ? at the end of it

   var Answers2="",Questions2="";
   //add ~~ as a sperator
   for(var i=0;i<QuestionL.length;i++) if(i<QuestionL.length-1) Questions2=Questions2+""+QuestionL[i]+"~~"; else Questions2=Questions2+""+QuestionL[i]; 
   for(var i=0;i<AnswerL.length;i++) if(i<AnswerL.length-1) Answers2=Answers2+""+AnswerL[i]+"~~"; else Answers2=Answers2+""+AnswerL[i];

   var Title=FilterQuestion(KBName.value,false);
   localStorage.setItem("mikesQuestions", Title+"~~"+Questions2);
   localStorage.setItem("mikesAnswers", Answers2); 

function LoadQuestions()
   var GQ,GA;
   if (localStorage.mikesAnswers) {GQ=localStorage.getItem("mikesQuestions");GA=localStorage.getItem("mikesAnswers");}
   else {QuestionL=[];AnswerL=[];return;}

   QuestionL=GQ.split("~~"); KBName.value=QuestionL[0]; //Title;
   QuestionL.splice(0,1); //remove the title
   AnswerL=GA.split("~~"); //separate text into an array

Save & Load to text files

   var textFile = null;
   function makeTextFile(text) //makes a url with the data so it can be downloaded
      var data = new Blob([text], {type: 'text/plain'});
      if (textFile !== null)  window.URL.revokeObjectURL(textFile);  //If replacing previous revoke to free memory   
      textFile = window.URL.createObjectURL(data);
      return textFile; //needs this for download button click to work

   Backup.addEventListener('click', function () { //When click 'Backup' button 
      var link = document.getElementById('downloadlink');
      var Title=FilterQuestion(KBName.value,false);

      var Questions2="",Answers2="";
      for(var i=0;i<QuestionL.length;i++) Questions2=Questions2+QuestionL[i]+"~~";
      for(var i=0;i<AnswerL.length;i++) if(i<AnswerL.length-2) Answers2=Answers2+AnswerL[i]+"~~"; else Answers2=Answers2+AnswerL[i];

      link.href = makeTextFile(Text2.value); //if want to see add = 'block';;  //so user does not need to click.
   }, false);

function openFile(event) {  //When click 'Restore'
   var input =;
   var reader = new FileReader();
   reader.onload = function()
      if(document.getElementById("getFile").value=="") return;
      var text = reader.result;
      var textArray=text.split("~~"); //turn text into an array
      NumberOfQuestions=parseInt(textArray[1]); //change from string to number
      QuestionL=textArray.slice(2, NumberOfQuestions+2);
      autocomplete(myQuestion, QuestionL,AnswerL); //call again so updates autocomplete
      SaveQuestions("from loaded text restoring"); //write over the previous local questions
      document.getElementById("getFile").value=""; //so it can load the same file twice

Functions to Remove Questions

function RemoveQuestion() //when user chooses to remove an answer from local
   OnQuestion = FindQ();
   if (OnQuestion > -1) {
      QuestionL.splice(OnQuestion, 1);
      AnswerL.splice(OnQuestion, 1);
      autocomplete(myQuestion, QuestionL,AnswerL);

function RemoveQuestions() //only removes local, txt files need to be deleted by user
   if(confirm("Clear all questions & answers.") )
      autocomplete(myQuestion, QuestionL,AnswerL);

Runs When Page Finishes Loading

function OnLoad() 
  autocomplete(myQuestion, QuestionL,AnswerL);

How to Copy and Paste Code

Open a text editor like Notepad or Wordpad. Copy and paste the html code with buttons. Then copy the javascript in order, pasting it between the script tags. Save the file with a name like QnASearch.htm so you can open it in a browser. Make sure you pay attention to file's location. View your computer files and find the folder. Then double click to open the file.

You should see the question and answer search engine. The knowledge base will be empty. So you will need to fill it by asking and answering questions. It is intended to be used as an offline webpage. You open it in a web browser but you don't need to be online.

Load data from a text file online.

//fetches a file named KB that was uploaded with your HTML file
   .then(response => response.text())
   .then((data) => {
      alert(data); //to see that it worked
     //move the data to variables

Sharing & Using Your Knowledge Base

This program is good for getting your computer to remember things for you. You can also share your knowledge or get other people to share information by sharing the text files created with the "Backup" button. The easiest way would be to email the file. Another way to share a knowledge base is to load it into a web page. Upload a text file with the questions and answers. Then get a web page to load the information using the onload function and fetch code shown above.

After creating a knowledge base you can get other web pages and programs to load and use the data. You could use it for games, chat bots, a FAQ page, help pages, expert systems, etc. Instead of just answering questions you ask the program could fill in for you in your absence. A computer program could make decisions based on your knowledge and respond the way you would.

This content is accurate and true to the best of the author’s knowledge and is not meant to substitute for formal and individualized advice from a qualified professional.

© 2019 Michael H


Michael H (author) from Canada on December 22, 2019:

Type a question like "How to convert 2D image to 3D?" and press enter. The answer area will be blank. To add an answer you need to click on the answer area, add the answer and click the "Answer" button.

Navneet on December 21, 2019:

How can I add questions in it?

Navneet on December 21, 2019:

Sir it's not working can I get whole code in a single html file?