Resizable

http://storehouse.sakura.ne.jp/resizable/resizable.htm
これ見て「すごいなー」と思ったので、prototype.jsで実装してみた。
Operaだとイマイチな動作。

<html>
  <head>
    <script src="prototype.js" type="text/javascript"></script>
    <script type="text/javascript">
var Resizable = Class.create();
Resizable.prototype = {
  initialize: function(element, options) {
    this.options = Object.extend({ margin:16 }, options || {});
    this.element = $(element);
    this.observe();
  },

  observe: function() {
    var resize = null;

    this.element.observe('mousemove', function(e) {
      if (resize) { return true; }
      var edge = this.edge(e);
      var style_cursor = edge ? (edge + '-resize') : 'auto';
      this.element.setStyle({ cursor:style_cursor });
      return true;
    }.bindAsEventListener(this));

    Element.observe(document, 'mousemove', function(e) {
      if (!resize) { return true; }
      e.stop();
      resize(e);
      return false;
    }.bindAsEventListener(this));

    Element.observe(document, 'mouseup', function(e) {
      if (!resize) { return true; }
      e.stop();
      resize = null;
      Element.setStyle(document.documentElement || document.body || this.element, { cursor:'auto' });
      return false;
    }.bindAsEventListener(this));

    this.element.observe('mousedown', function(e) {
      var edge = this.edge(e);
      if (!edge) { return true; }
      e.stop();
      Element.setStyle(document.documentElement || document.body || this.element, { cursor:(edge + '-resize') });
      resize = this.make_resize(e.pointer(), this.element.getDimensions(), edge);
      return false;
    }.bindAsEventListener(this));
  },

  make_resize: function(origin_pnt, origin_dim, edge) {
    return (function(e) {
      var pnt = e.pointer();
      var style = {};

      if (edge.indexOf('s') >= 0) {
        style.height = origin_dim.height + pnt.y - origin_pnt.y;
      }

      if (edge.indexOf('e') >= 0) {
        style.width = origin_dim.width + pnt.x - origin_pnt.x;
      }

      this.element.setStyle(style);
    }.bind(this));
  },

  edge: function(e) {
    var pos = this.element.positionedOffset();
    var dim = this.element.getDimensions();
    var pnt = e.pointer();
    var south = ((pos.top + dim.height - pnt.y) < this.options.margin) ? 's' : '';
    var east = ((pos.left + dim.width - pnt.x) < this.options.margin) ? 'e' : '';
    return (south + east);
  }
};
    </script>
  </head>
  <body>
    <div id="foo" style="width:100px; height:100px; border:1px solid black;"></div>
    <textarea id="bar"></textarea>
    <script type="text/javascript">
      new Resizable('foo');
      new Resizable('bar');
    </script>
  </body>
</html>

ぜんぜん関係ないけど、「$('foo').setStyle(...)」の書き方ってあんまり普及していないのかなぁ?