12 May, 2016
by fabiovalse

Wikidata search panel

This gist just call the MediaWiki API in order to retrieve resources from Wikidata. Textual researches can be perfomerd using the search box.

At the time this gist has been built, Wikidata does not allow to perform requests from client-side (e.g, ajax calls). A api.php script has been used in order to retrieve data. Unfortunately, since bl.ocks.org can not be run server-side code, it is possible to look at a working version here.

<?php
  header("Content-Type: application/json");
  
  $text = urlencode($_GET['text']);
  $final_result = array();

  $languages = array('en', 'it', 'fr', 'de', 'es');
  
  /* A call to the wikidata API is perfomed until the search-continue attribute is present in the API result
  */
  foreach ($languages as $lang) {

    $offset = 0;

    do {
      $result = json_decode(file_get_contents("https://www.wikidata.org/w/api.php?action=wbsearchentities&type=item&search=$text&limit=max&continue=$offset&language=$lang&format=json"), true);

      if (isset($result['search-continue']))
        $offset = $result['search-continue'];

      $final_result = array_merge($final_result, $result['search']);

    } while (isset($result['search-continue']));

  }

  echo json_encode(array_merge(array_unique($final_result, SORT_REGULAR), array()));
?>
search_results = d3.select '#search_results'
  .attr
    height: 458

search_input = d3.select '#header input'
  .on 'keydown', () ->
    if event.keyCode is 13
      search()

d3.select '#search_button'
  .on 'click', () ->
    search()

search = (_offset) ->
  query_string = d3.select('#header input').node().value

  if query_string isnt ''
    d3.json "api.php?text=#{query_string}", (error, data) ->

      results = search_results.selectAll '.result'
        .data data, (d,i) -> "#{d.id}"

      enter_results = results.enter().append 'div'
        .attr
          class: 'result'

      results.order()

      resource = enter_results.append 'div'
        .attr
          class: 'resource'  
      resource.html (d) -> "<span class='label'>#{d.label}</span> <span>(<a target='_blank' class='link' href='#{d.concepturi}'>#{d.id}</a>)</span>"

      description = enter_results.append 'div'
        .attr
          class: 'description'
      description.text (d) -> d.description

      results.exit().remove()
html, body {
  margin: 0;
  padding: 0;
  width: 100%;
  height: 100%;
  font-family: sans-serif;
  font-size: 15px;
}

/*  HEADER
*/
#header {
  padding: 5px;
}
#header input {
  width: 30%;
  height: 30px;
  font-size: 15px;
}
#header #search_button {
  width: 60px;
  height: 32px;
  background: #d0d0d0;
  font-size: 15px;
  border: 0;
  color: #fff;
  border-radius: 3px;
  cursor: pointer;
}

/* SEARCH RESULTS
*/
#search_results {
  padding: 5px;
  height: 458px;
  overflow: scroll;
  overflow-x: hidden;
}

.result {
  margin: 5px 0px 5px 5px;
}

.result .link {
  color: steelblue;
}
.result .link:hover {
  text-decoration: none;
}

.result .description {
  color: #999;
  font-style: italic;
  font-size: 13px;
}
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
    <link rel="stylesheet" href="index.css">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css">
    <script src="http://d3js.org/d3.v3.min.js"></script>
  </head>
  <body>

    <div id="header">
      <input type="text">
      <button id="search_button" title="Find"><i class="fa fa-search"></i></button>
    </div>

    <div id="search_results"></div>

    <script src="index.js"></script>
  </body>
</html>
// Generated by CoffeeScript 1.10.0
(function() {
  var search, search_input, search_results;

  search_results = d3.select('#search_results').attr({
    height: 458
  });

  search_input = d3.select('#header input').on('keydown', function() {
    if (event.keyCode === 13) {
      return search();
    }
  });

  d3.select('#search_button').on('click', function() {
    return search();
  });

  search = function(_offset) {
    var query_string;
    query_string = d3.select('#header input').node().value;
    if (query_string !== '') {
      return d3.json("api.php?text=" + query_string, function(error, data) {
        var description, enter_results, resource, results;
        results = search_results.selectAll('.result').data(data, function(d, i) {
          return "" + d.id;
        });
        enter_results = results.enter().append('div').attr({
          "class": 'result'
        });
        results.order();
        resource = enter_results.append('div').attr({
          "class": 'resource'
        });
        resource.html(function(d) {
          return "<span class='label'>" + d.label + "</span> <span>(<a target='_blank' class='link' href='" + d.concepturi + "'>" + d.id + "</a>)</span>";
        });
        description = enter_results.append('div').attr({
          "class": 'description'
        });
        description.text(function(d) {
          return d.description;
        });
        return results.exit().remove();
      });
    }
  };

}).call(this);
File not shown (binary encoding).