1
\$\begingroup\$

The goal is to query the Wikipedia API with a search, and present the user the autocomplete options based on an API call that shows possible Wikipedia pages when entering the search using the jQuery autocomplete widget.

The project works and is able to query the Wikipedia API, but I am not happy with the autocomplete feature; it appends to the DOM instead of accepting the <div> container as per the documentation. I tried several techniques to change the autocomplete location (as commented out) but the autocomplete object always appears to the left of the search input. Ideally, I would like to show the autocomplete options below the search input space. Any suggestions would be welcome, in addition to any suggestions on how I can improve the overall program design.

$("#searchFor").autocomplete({
    source: function(request, response) {
        $.ajax({
            url: "http://en.wikipedia.org/w/api.php",
            dataType: "jsonp",
            data: {
                'action': "opensearch",
                'format': "json",
                'search': request.term
            },
            success: function(data) {
                 response(data[1]);
            }
        })
      },
//      after: $('#mainDisp'),
//    appendTo: $('#mainDisp'), 
//    position: {my:"left top", at: 'left bottom', of: "#mainDisp"},
    select: function(event, ui){
      var fistOfFirst = ui.item.label;
      console.log(fistOfFirst);
      $("#mainDisp").empty();
      searchFx();
}
})

$("#searchBtn").on('click', function(event){
  $("#mainDisp").empty();
  searchFx()
  });
                   
function searchFx(){
    var searchInput = $('#searchFor').val();
    var tgtSite = "https://en.wikipedia.org/w/api.php?action=opensearch&list=search&srwhat=text&srprop=snippet&utf8=1&continue=&format=json&search=" + searchInput;
    sendRequest(tgtSite);
}

function sendRequest(tgtSite){
    $.ajax({
      url: tgtSite,
      dataType: 'jsonp',
      data: { 
        q:{}, 
        format: 'json' },
        success: organizeData })
}

function organizeData(data){
  if (typeof(data) != "object") {
    updateView("Please retry term");
  }
  var title, snippet, hLink, replyLength, singleReply;
  title = data[1];
  snippet = data[2];
  hLink = data[3];
  replyLength = title.length;
  singleReply = [];
  
  for (var i = 0; i < replyLength; i++){
    singleReply.push(title[i]);
    singleReply.push(snippet[i]);
    singleReply.push(hLink[i]);
    updateView(singleReply);
    singleReply = [];
  }
}

function updateView(queryReply){
  var mainDisp = document.getElementById('mainDisp');
  
  var titleMessageElement = document.createElement('p');
  var titleDisp = document.createTextNode(queryReply[0]);
  titleMessageElement.className = "retTitle";
  
  var snippetMessageElement = document.createElement('p');
  var snippetDisp = document.createTextNode(queryReply[1]);
  
  var linkMessageElement = document.createElement('a');
  linkMessageElement.setAttribute('href', queryReply[2]);
  linkMessageElement.innerHTML = queryReply[2];
  linkMessageElement.className = 'linkFormat';
  
  var outShell = document.createElement('div');
  var innShell = document.createElement('div'); 
  outShell.className = "outerShell";
  innShell.className = 'innerShell';
  
  titleMessageElement.appendChild(titleDisp);
  snippetMessageElement.appendChild(snippetDisp);
  
  innShell.appendChild(titleMessageElement);
  innShell.appendChild(snippetMessageElement);
  innShell.appendChild(linkMessageElement);
  
  outShell.appendChild(innShell);
  
  mainDisp.appendChild(outShell);
}
body {
  background-color: white;
  color: black;
}

.search {
  background-color: rgba(89, 89, 89, 0.4);
  border-radius: 100px;
  font-size: 2em;
  text-align: center;
}

#lower {
  margin: 1.2em;
}

#randBtn {
  float: right;
  background-color: rgba(0,0,0, 0.7);
  margin: 0.2em;
  padding: 0.3em;
  font-size: 1.2em;
  color: white;
}

a {
  color: white;
  text-decoration: none;
}

#searchBtn {
  background-color: blue;
  color: white;
  font-size: 1.2em;
  padding: 0.3em;
}

.shell {
  position: absolute;
  display: block;
  width: 100%;
  top: 10%;
}

.main {
  text-align: center;
  margin: auto;
  width: 80%;
}

p {
  padding: 5px;
  color: black;
  font-family: 'Open Sans', sans-serif;
}

#intro {
  font-size: 2em;
  margin: 0 0 0.5em 0;
}

p.retTitle {
  color: rgb(128, 0 , 0);
}

.linkFormat {
  padding: 5px;
  color: yellow;
}

.outerShell {
  position: relative;
  width: 100%;
  margin: auto;
}

.innerShell {
  border: solid 1px #fff;
  border-radius: 50px;
  background-color: rgba(38, 38, 38, 0.6);
  width: 80%;
  text-align: center;
  margin: 0.5em auto 0.5em;
  padding: 0.25em;
}
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Wikipdia Qs</title>

  <script src="https://code.jquery.com/jquery-3.1.1.min.js" integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8=" crossorigin="anonymous"></script>

  <link href="https://fonts.googleapis.com/css?family=Open+Sans" rel="stylesheet">
  <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
  <link rel="stylesheet" href="wk2.css">
</head>
<body >
  
  <button id="randBtn" class="search"><a href="https://en.wikipedia.org/wiki/Special:Random"><i> Or A Random Article...</i></a></button>
  
  <div class="shell">
  <div class="main">
  <p id="intro">Tell me about... </p>
<div id="lower">
  <input type="text" class="search" id="searchFor" value="?" >
  <button id="searchBtn" class="search"><i class="material-icons">search</i></button>
    </div></div>
  
    <div id="mainDisp"></div>

<script src="wk2.js"></script>
    
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.3/themes/smoothness/jquery-ui.css" />
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.3/jquery-ui.min.js"></script>    
    
</body>
</html>

\$\endgroup\$
  • \$\begingroup\$ I'll suggest to use jQuery as you've included it. updateView() can be completely rewritten in jQuery. The for inside organizeData() can be written as updateView(title[i], snippet[i], hLink[i]) \$\endgroup\$ – Tushar Oct 18 '16 at 4:21
  • \$\begingroup\$ Have you tried putting the link the jquery ui css in the head? \$\endgroup\$ – RobH Oct 18 '16 at 14:26
  • \$\begingroup\$ Thank you for the feedback. @Tushar I like the three argument version of updateView, it makes it much cleaner to send the values in by name rather than position in the array. Thank you. \$\endgroup\$ – Cameron Oct 18 '16 at 19:38
  • \$\begingroup\$ @RobH I don't know what happened with the jquery ui css, when I was building I got an error because it wouldn't find the input box unless it was at the end of the html, but when I was updating now I had to have it in the head in order to see autocomplete function. Thanks for the catch. \$\endgroup\$ – Cameron Oct 18 '16 at 19:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.