JS.20 Formの登録内容を可視化する。

JS.19でフォトギャラリーを作成したので、これを用いてアノテーションを楽にするツールの作成を試みる。

キーボードから楽にアノテーションができるようにするため、属性(attribute)に対して(複数の)ラベル(label)とそれに対応するキー(key)用意し、それぞれキーボードから指定可能にした。

  1. Registration で属性(attribute)に対する(複数の)ラベル(label)とそれに対応するキー(key)を登録する。
  2. 登録した内容は、Registered Attributesに記載されています。
  3. 全ての属性の登録が済んだら、画像をクリックしてフォーカス状態にする。
  4. その状態で先ほど登録したキーを入力すれば、対応するラベルが対応する属性に付加される。
  5. download ボタンを押せば、json形式でダウンロード可能。

Registration

Attributes:
Key Label Copy Delete

Registered Attributes

attribute label command
attribute current label

コード

html

<div class="annotation-attrs">
  <div class="registration-col" style="margin-left: 10px; float: left;">
    <h2>Registration</h2>
    <form id="registration-attrs-form" action="#" onsubmit="return false;">
      <table>
        <thead id="registration-attrs-thead">
          <tr><th colspan="4">Attributes: <input id="attr-name" type="text" class="form-control" placeholder="attribute" required></th></tr>
          <tr>
            <th>Key</th>
            <th>Label</th>
            <th>Copy</th>
            <th>Delete</th>
          </tr>
        </thead>
        <tbody id="registration-attrs-tbody">
          <tr>
            <td><input type="text" class="command-key" maxlength="1" size="1"></td>
            <td><input type="text" class="label-name"  placeholder="label name"></td>
            <td><input type="button" value="+" class="add" tabindex="-1"></td>
            <td><input type="button" value="-" class="del" tabindex="-1"></td>
          </tr>
        </tbody>
        <tbody id="registration-attrs-ttail">
          <tr><td colspan="4">
            <input id="form-reset" type="reset" name="reset" value="Clear"/>
            <input type="submit" value="Register" onclick="return register_attrs();">
          </td></tr>
        </tbody>
      </table>
    </form>
  </div>
  <div class="registration-col" style="margin-right: 10px; float: right;">
    <h2>Registered Attributes</h2>
    <table id="registered-attrs">
      <thead id="registered-attrs-thead">
        <tr>
          <th>attribute</th>
          <th>label</th>
          <th>command</th>
        </tr>
      </thead>
      <tbody id="registered-attrs-tbody">
      </tbody>
    </table>
  </div>
</div>
<div class="sample-box" style="text-align: center; width: 50%; margin: 0 auto;">
  <a href="#" id="img-wrapper">
    <img id="sample-img" src="https://iwasakishuto.github.io/images/profile/twitter.png">
  </a>
  <table id="annotation-label">
    <thead id="annotation-label-thead">
      <tr>
        <th>attribute</th>
        <th>current label</th>
      </tr>
    </thead>
    <tbody id="annotation-label-tbody">
    </tbody>
  </table>
  <button onclick="download_json();">download</button>
</div>

js

jqueryを使用した。

// Add and Delete input tags.
$(document).on("click", ".add", function() {
  var target = $(this).parent().parent()
  target.clone(true).insertAfter(target);
});
$(document).on("click", ".del", function() {
  var target = $(this).parent().parent();
  if (target.parent().children().length > 1) {
    target.remove();
  }
});
var sample_img_annotation = {}
$("#img-wrapper").keydown(function(event) {
  const key = event.key;
  if (command_keys.hasOwnProperty(key)){
    attr_label = command_keys[key]
    sample_img_annotation[attr_label[0]] = attr_label[1]
  }
  generate_annotation_table()
});
// Cancel Default event.
document.getElementById("img-wrapper").addEventListener("click", function(e){
  e.preventDefault();
}, false);
// Change background-color when input is focused.
$(function() {
  $('input[type="text"]')
    .focusin(function(e) {
      $(this).css('background-color', '#ffc');
    })
    .focusout(function(e) {
      $(this).css('background-color', '');
    });
});
// Register Annotation labels.
var anno_dataset = {}
var command_keys = {}
function register_attrs(){
  var attr_name = $("#attr-name")[0].value;
  var msg = "";
  if (attr_name!=""){
    if (attr_name in anno_dataset){
      msg += "[×] ".concat("Attribute ", attr_name, " is already registered.", "\n");
    }else{
      var attrs = {}
      msg += "[○] ".concat("Attribute ", attr_name, " is registered.", "\n");
      $("#registration-attrs-tbody").children("tr").each(function(i, e) {
        let inputs = e.getElementsByTagName("input");
        let key    = inputs[0].value;
        let label  = inputs[1].value;
        if (key!="" && label!=""){
          if (command_keys.hasOwnProperty(key)){
            msg += "\t[×] ".concat(key, " is already used.", "\n");
          }else{
            command_keys[key] = [attr_name, label];
            attrs[key] = label;
            msg += "\t[○] ".concat(key, " is registered to mean label: ", label, "\n");
          }
        }
      });
      anno_dataset[attr_name] = attrs;
    }
  }else{
    msg += "[×] Please enter 'Attribute name'.\n";
  }
  alert(msg);
  reset_registration_table();
  generate_registered_table();
  generate_annotation_table();
  return false;
}
// Reset Registration Form table.
function reset_registration_table(){
  $("#form-reset").click();
  del_btns = $("input[class='del']");
  for (let i=0; i<del_btns.length; i++){
    del_btns[i].click();
    console.log(del_btns[i])
  }
}
// Generate Registered Attributes table.
function generate_registered_table(){
  var registered_tbody = $("#registered-attrs-tbody");
  registered_tbody.empty();
  for (let attr_name in anno_dataset){
    let attrs = anno_dataset[attr_name];
    let num_labels = Object.keys(attrs).length;
    var row = "";
    var is_attr_added = false;
    for (let key in attrs){
      row += "<tr>"
      if (!is_attr_added){
        row += "<td rowspan='" + num_labels +  "'>" + attr_name + "</td>";
        is_attr_added = true;
      }
      row += "".concat("<td>", attrs[key], "</td>");
      row += "".concat("<td>", key, "</td>");
      row += "</td>"
    }
    registered_tbody.append(row);
  }
}
// Generate annotation table.
function generate_annotation_table(){
  var annotation_tbody = $("#annotation-label-tbody");
  annotation_tbody.empty();
  var row = ""
  for (let attr_name in anno_dataset){
    var label = sample_img_annotation[attr_name];
    var label = typeof(label) == "undefined" ? "" : label
    row += "".concat("<tr>", "<td>", attr_name, "</td>", "<td>", label, "</td>");
  }
  annotation_tbody.append(row);
}
function download_json(){
  var jsonString = JSON.stringify(sample_img_annotation, null, '\t');
  var blob = new Blob([jsonString], {type: 'application/json' });
  let link = document.createElement('a');
  link.href = window.URL.createObjectURL(blob);
  link.download = 'annotations.json';
  link.click();
}
other contents
social