sticky.js(作りかけ)

JavaScript

var Sticky = Class.create();
Sticky.prototype = {
  initialize: function(id, contents, top, left) {
    this.id = id;
    this.table = Builder.node('table', {id:id, className:'sticky'}, [
                   Builder.node('tbody', {}, [
                     Builder.node('tr', {}, [
                       Builder.node('td', {}, [
                         Builder.node('div', {}, contents),
                         Builder.node('div', {}, [
                           Builder.node('textarea', {}, contents)]) ]) ]) ]) ]);

    this.td = this.table.getElementsByTagName('td')[0];
    var viewer_editor = this.td.getElementsByTagName('div');
    this.viewer = viewer_editor[0];
    this.editor = viewer_editor[1];
    this.textarea = this.editor.getElementsByTagName('textarea')[0];
    this.draggable = new Draggable(this.table);

    Draggables.addObserver({
      onEnd: function(eventName, draggable, event) {
        (draggable == this.draggable) && this.onmove && this.onmove(this);
      }.bind(this)
    });
    Event.observe(this.td,       'dblclick', function() { this.edit() }.bindAsEventListener(this));
    Event.observe(this.textarea, 'change', function() {
      this.viewer.innerHTML = this.textarea.value;
    }.bindAsEventListener(this));
    Event.observe(this.textarea, 'blur', function() {
      this.view();
      this.onedit && this.onedit(this);
    }.bindAsEventListener(this));

    this.hide();
    this.view();
    this.position(top, left);
  },
  attach: function(board) {
    this.board = $(board);
    this.board.appendChild(this.table);
    this.show();
    this.onattach && this.onattach(this);
  },
  detach: function() {
    this.hide();
    this.board.removeChild(this.table);
    this.ondetach && this.ondetach(this);
  },
  show: function() {
    Element.setStyle(this.table, {visibility:'visible'});
  },
  hide: function() {
    Element.setStyle(this.table, {visibility:'hidden'});
  },
  view: function() {
    Element.hide(this.editor);
    Element.show(this.viewer);
  },
  edit: function() {
    Element.hide(this.viewer);
    Element.show(this.editor);
    this.textarea.focus();
  },
  position: function(top, left) {
    var style = {};
    top  && (style.top  = top );
    left && (style.left = left);
    Element.setStyle(this.table, style);
  },
  contents: function() {
    return this.textarea.value;
  },
  top: function() {
    return Element.getStyle(this.table, 'top');
  },
  left: function() {
    return Element.getStyle(this.table, 'left');
  },
  setStyle: function(style) {
    Element.setStyle(this.td, style);
  }
};

CSS

.sticky td {
  background-color: white;
  border-top:       1px solid #ddd;
  border-left:      1px solid #ddd;
  border-bottom:    1px solid gray;
  border-right:     1px solid gray;
  padding:          2px;
  white-space:      nowrap;
}

.sticky textarea {
  background-color: #eee;
  border-top:       1px solid gray;
  border-left:      1px solid gray;
  border-bottom:    1px solid #ddd;
  border-right:     1px solid #ddd;
}

実装すること

  • テキストエリア編集時、自動的にテキストのサイズに合わせる
  • テキストエリア編集中にリサイズできるようにする(または、十分な大きさのテキストエリア)
  • viewモードでのHTML・空白・改行のエスケープ・アンエスケープ
  • コンテンツがカラになったときの対応。