LoginSignup
2
1

More than 3 years have passed since last update.

SPARQLエンドポイント簡易検索アプリをjQueryからVue.jsに書き直しました

Last updated at Posted at 2020-08-03

RDFデータベースをSPARQLと呼ばれるクエリ言語で検索できるWeb API「SPARQLエンドポイント」を公開するオープンデータサイトが行政を中心に増えています。例えば、

これらのサイトの多くは、Webブラウザ上でSPARQLクエリを実行して、表形式で検索結果を見られるようになっています。
しかし、Web APIなので本来は仕様に基づいた形式でエスケープ処理をしたSPARQLクエリをGETもしくはPOSTしなけれならないので、上記のような気の利いたページを公開しないSPARQLエンドポイントもあります。

そこでだいぶ前にWebブラウザ上でSPARQLエンドポイントへ簡単にSPARQLクエリを実行できて、その結果を見やすい表形式で表示するWebアプリをjQueryで作りました。

JavaScriptによるSPARQL利用サンプル(クエリ検索アプリ)
https://github.com/uedayou/simple-sparqlsearch-js

JavaScriptによるSPARQL利用サンプル(クエリ検索アプリ)

かなり古いアプリですが、今でも問題なく動きます。ただ、今見るとコードの可読性が悪いなとおもいます。とても短いコードでもあるので、jQueryを使わずに書き直すことにしました。

Vue.js で書き直し

今回は Vue.js を使うことにしました。React, AngularでもWebアプリを書いたことがありますが、今回はできるだけコード量を減らして、Webpack等でのビルドを行わない形にしたかったので、Vue.jsを使いました。

Vue.jsによるSPARQLエンドポイント検索アプリ
https://github.com/uedayou/simple-sparqlsearch-vue

Vue.jsによるSPARQLエンドポイント検索アプリ

機能としては全く同じですが、検索した結果をJSONファイルでダウンロードできるようにしました。

ダウンロード

検索結果が表示されているときに、ダウンロードボタンを押すとJSONファイルがダウンロードできます。

Vue.js vs jQuery

Vue.js で書き直してみて、jQueryのコードよりも個人的には格段に可読性が上がったと思います。
jQueryは、DOM操作をコード内で行わないといけなかったのが、Vue.jsだとDOMにデータをバインディングできるので書き直すのも楽にできました。

Vue.jsのコード
Vue.use(VueLoading);
Vue.component('loading', VueLoading);

var app = new Vue({
  el: '#app',
  data: {
    query: 'select * where {?s ?p ?o} LIMIT 10',
    results: {
      data: null,
      head: [],
      body: [],
    },
  },
  methods: {
    doSearch: function() {
      var loader = this.$loading.show();
      var that = this;
      axios.get(
        endpoint+"?query="+encodeURIComponent(this.query),
        { headers: {'Accept': 'application/sparql-results+json'} })
      .then(function(res) {
        that.results.data = res.data;
        that.results.head = res.data.head.vars;
        that.results.body = res.data.results.bindings;
      })
      .catch(function(error) {
        console.log(error);
        alert("Error!");
      })
      .then(function() {
        loader.hide();
      });
    },
    downloadData: function() {
      var filename = "results.json";
      var a = document.createElement('a');
      var uriContent = 'data:application/octet-stream,'+encodeURIComponent(JSON.stringify(this.results.data));
      a.setAttribute('href', uriContent);
      a.setAttribute('download', filename);
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
    }
  }
})

jQueryのコード
(function(){
  $.fn.modal.defaults.spinner = $.fn.modalmanager.defaults.spinner = '<div class="loading-spinner" style="width: 200px; margin-left: -100px;"><div class="progress progress-striped active"><div class="progress-bar" style="width: 100%;"></div></div></div>';
  $('#find_query').click(function(){
    $('body').modalmanager('loading').find('.modal-scrollable').off('click.modalmanager');
    qr = sendQuery(endpoint,encodeURIComponent($('#query_area').val().replace(/[\n\r]/g,"")));
    qr.fail(
      function (xhr, textStatus, thrownError) {
        $('body').modalmanager('removeLoading');
        alert("Error: A '" + textStatus+ "' occurred.");
      }
    );
    qr.done(
      function (d) {
        $('body').modalmanager('removeLoading');
        $('body').removeClass('modal-open');
        result_table(d.results.bindings);
      }
    );
  });
  $('#result_div').hide();
}());

var result_table = function(data){
  var result_div = $('#result_div');
  var table = $('#result_list')[0];
  if (table == undefined) {
    result_div.append($('<table></table>').attr({
      'id' : 'result_list',
      'class' : 'table'
    }));
    table = $('#result_list')[0];
  }
  while (table.rows.length > 0) { table.deleteRow(0); }
  if (data instanceof Array) {
    result_div.show();
    var header = table.createTHead();
    var headerRow = header.insertRow(0);
    id = 1;
    for (var d = 0; d < data.length; d++) {
      var row1 = table.insertRow(d + 1);
      if (d == 0) {
        for ( var key in data[0]) {
          var th = document.createElement('th');
          var label = key;
          th.innerHTML = key;
          headerRow.appendChild(th);
        }
      }
      var i = 0;
      for ( var key in data[d]) {
        var cell = row1.insertCell(i++);
        var value = data[d][key];
        if (value.value != undefined){value = value.value;}
        if (value == null) {value = '';}
        var link = true;
        if (link) {
          if (value != null && value.indexOf("http://") == 0) {
            value = '<a href="'+value+'" target="_blank">'+value+'</a>';
          }
        }
        cell.innerHTML = value;
      }
    }
  }
};
2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1