おもしろwebサービス開発日記

Ruby や Rails を中心に、web技術について書いています

OpenSocial勉強会の課題サンプルコード

OpenSocial Host勉強会用のサンプルコードと課題 - おもしろWEBサービス開発日記に書いた課題の答え的なサンプルコードです。 本当は会社のブログに書いておきたかったのですが、WordPressの扱いにまだ慣れてなく、プログラムソースをきれいに表示させるのに時間がかかりそうなので一時的にこちらに置いておきます*1

完了ボタンを押したときにtodoデータを削除するようにしてみましょう

xmlOpenSocial Host勉強会用のサンプルコードと課題 - おもしろWEBサービス開発日記に書いてあるものと同じです。

function init () {
  var viewer;
  var viewer_id;
  var insert = document.getElementById("insert");
  var todo = document.getElementById("todo");
  var req = opensocial.newDataRequest();
  var remove;
  var li;
  req.add(req.newFetchPersonRequest(opensocial.IdSpec.PersonId.VIEWER), "viewer");
  // viewer idの取得
  req.send(function(data) {
    viewer = data.get('viewer').getData();
    viewer_id = viewer.getId();
    var conditions = {};
    conditions[opensocialhost.data.SearchConditions.KEY] = viewer_id + "-";
    // viewerのtodoをsearch apiを利用して取得
    opensocialhost.data.search(conditions, function (response){
      if (response.hadError) {
        alert(response.errorCode);
      } else {
        if (response.total_counts) {
          for(var i = 0; i < response.data.length; i++) {
            li = document.createElement("li");
            remove = document.createElement("input");
            remove.type = "button";
            remove.value = "完了";
            remove.onclick = (function () {
              var key = response.data[i].key;
              return function () {
                // remove apiを利用してtodoを削除
                opensocialhost.data.remove(key, function (response){
                  var li;
                  if (response.hadError) {
                    alert(response.errorCode);
                  } else {
                    li = document.getElementById(key);
                    todo.removeChild(li);
                  }
                });
              };
            })();
            li.id = response.data[i].key;
            li.appendChild(document.createTextNode(response.data[i].value));
            li.appendChild(remove);
            todo.appendChild(li);
            gadgets.window.adjustHeight();
          }
        }
      }
    });
  });
  insert.onclick = function () {
    var value = document.getElementById("new_todo").value;
    var now = new Date();
    var key = viewer_id + "-" + now.toLocaleString();
    // パーミッションを設定して他の人に見られないように
    var permissions = {};
    permissions["READ_PERMISSION"] = opensocialhost.data.PermissionType.PRIVATE;
    permissions["WRITE_PERMISSION"] = opensocialhost.data.PermissionType.PRIVATE;
    // insert apiを利用してtodoを追加
    opensocialhost.data.insert(key, value, permissions, function (response) {
      if (response.hadError) {
        alert(response.errorCode);
      } else {
        li = document.createElement("li");
        li.appendChild(document.createTextNode(value));
        li.id = key;
        remove = document.createElement("input");
        remove.type = "button";
        remove.value = "完了";
        remove.onclick = function (response) {
          // remove apiを利用してtodoを削除
          opensocialhost.data.remove(key, function (response){
          var li;
          if (response.hadError) {
            alert(response.errorCode);
          } else {
            li = document.getElementById(key);
            todo.removeChild(li);
          }
          });
        };
        li.appendChild(remove);
        todo.insertBefore(li, todo.firstChild);
        gadgets.window.adjustHeight();
      }
    });
  };
};

gadgets.util.registerOnLoadHandler(init);

todoを修正できるようにしてみましょう

xmlOpenSocial Host勉強会用のサンプルコードと課題 - おもしろWEBサービス開発日記に書いてあるものと同じです。

削除機能を追加したソースにさらに修正を加えています。修正点は

  • todoをテキストからテキストフィールドに変更
  • 更新ボタンを追加

の二点です。テキストをテキストフィールドに動的に変更するような処理を行ったほうがいいかとも思ったのですが、本質と関係ない機能でソースが増えてしまうのでやってません。

function init () {
  var viewer;
  var viewer_id;
  var insert = document.getElementById("insert");
  var todo = document.getElementById("todo");
  var req = opensocial.newDataRequest();
  var remove;
  var update;
  var input;
  var li;
  req.add(req.newFetchPersonRequest(opensocial.IdSpec.PersonId.VIEWER), "viewer");
  // viewer idの取得
  req.send(function(data) {
    viewer = data.get('viewer').getData();
    viewer_id = viewer.getId();
    var conditions = {};
    conditions[opensocialhost.data.SearchConditions.KEY] = viewer_id + "-";
    // viewerのtodoをsearch apiを利用して取得
    opensocialhost.data.search(conditions, function (response){
      if (response.hadError) {
        alert(response.errorCode);
      } else {
        if (response.total_counts) {
          for(var i = 0; i < response.data.length; i++) {
            li = document.createElement("li");
            remove = document.createElement("input");
            remove.type = "button";
            remove.value = "完了";
            remove.onclick = (function () {
              var key = response.data[i].key;
              return function () {
                // remove apiを利用してtodoを削除
                opensocialhost.data.remove(key, function (response){
                  var li;
                  if (response.hadError) {
                    alert(response.errorCode);
                  } else {
                    li = document.getElementById(key);
                    todo.removeChild(li);
                  }
                });
              };
            })();
            update = document.createElement("input");
            update.type = "button";
            update.value = "更新";
            update.onclick = (function () {
              var key = response.data[i].key;
              return function () {
                var li = document.getElementById(key);
                var value = li.firstChild.value;
                // update apiを利用してtodoを更新
                opensocialhost.data.update(key, value, function (response){
                  if (response.hadError) {
                    alert(response.errorCode);
                  }
                });
              };
            })();
            remove.id = response.data[i].key;
            li.id = response.data[i].key;
            input = document.createElement("input");
            input.type = "input"
            input.value = response.data[i].value;
            li.appendChild(input);
            li.appendChild(update);
            li.appendChild(remove);
            todo.appendChild(li);
            gadgets.window.adjustHeight();
          }
        }
      }
    });
  });
  insert.onclick = function () {
    var value = document.getElementById("new_todo").value;
    var now = new Date();
    var key = viewer_id + "-" + now.toLocaleString();
    // パーミッションを設定して他の人に見られないように
    var permissions = {};
    permissions["READ_PERMISSION"] = opensocialhost.data.PermissionType.PRIVATE;
    permissions["WRITE_PERMISSION"] = opensocialhost.data.PermissionType.PRIVATE;
    // insert apiを利用してtodoを追加
    opensocialhost.data.insert(key, value, permissions, function (response) {
      if (response.hadError) {
        alert(response.errorCode);
      } else {
        li = document.createElement("li");
        li.id = key;
        input = document.createElement("input");
        input.type = "input"
        input.value = value;
        li.appendChild(input);
        remove = document.createElement("input");
        remove.type = "button";
        remove.value = "完了";
        remove.onclick = function (response) {
          // remove apiを利用してtodoを削除
          opensocialhost.data.remove(key, function (response){
            var li;
            if (response.hadError) {
              alert(response.errorCode);
            } else {
              li = document.getElementById(key);
              todo.removeChild(li);
            }
          });
        };
        update = document.createElement("input");
        update.type = "button";
        update.value = "更新";
        update.onclick = function () {
          var li = document.getElementById(key);
          var value = li.firstChild.value;
          // update apiを利用してtodoを更新
          opensocialhost.data.update(key, value, function (response){
            var li;
            if (response.hadError) {
              alert(response.errorCode);
            }
          });
        };
        li.appendChild(update);
        li.appendChild(remove);
        todo.insertBefore(li, todo.firstChild);
        gadgets.window.adjustHeight();
      }
    });
  };
};

gadgets.util.registerOnLoadHandler(init);

todoデータを自分以外の人に公開できるようにパーミッションを設定してみましょう

これはきちんとやると分量がすごいことになりそうなので省略します。

余談

サンプルソースのコードは汚いと思いますごめんなさい><あと一部クロージャを使っていてJavaScript初心者の方は何やってるかよくわからない部分があると思います。JavaScript: The Good Partsなどを読むとそのあたりわかると思うのでよろしければ参考にしてみてください。


OpenSocial HostのJavaScript APIはかなり簡単に使えてしまい(OpenSocialのプログラミングに慣れている人には特に)、アプリを作るにしてもJavaScriptOpenSocial本体のほうが厄介だったりするため、適切なチュートリアルを用意するのが難しかったりします。そのあたりをなんとか解決 & コードをきれいに書き直せたらOpenSocial Hostのヘルプにでもチュートリアルページを追加したいなと思います。

*1:というわけで後々このエントリは移動するかもしれません