2006-08-25 (Fri)

テキストエリアとかリサイズ可能にする JavaScript

好評の、読み込ませるだけシリーズ の6番目。

このスクリプトを読み込ませるだけで、ウェブ上にある TEXTAREA とかその他色々好きな要素がリサイズ可能なやつに大変身。とりあえずサンプル見るのが手っ取り早いです。

テキストエリアの右下にマウスカーソルを持っていくとカーソル形状がかわるので、そのままドラッグするとサイズも変わります。

自分はグリモンスクリプトで快適なんですが、サービス提供側でこういう機能を提供してくれたら幸せな人が増えるんじゃね?とか思ったので作ってみました。

実際のリサイズ方法に関しては、愛用している Changing <textarea> Size のコードが大変参考になりました。ありがとうございます。

コードは次の通りです。

メイン部分。

var ElementResizer = {
   moveNode: false,

   add: function(elm) {
      var obj = new this._ChildElement(this, elm);

      addEvent(elm, 'mousedown', function (e) {
         if(obj.resizePoint(e)) {
            ElementResizer.moveNode = obj;
         }
      });

      return obj;
   },

   start: function() {
      var self = this;
      addEvent(document.body, 'mouseup', function (e) {
         if(self.moveNode) self.moveNode = false;
      });

      addEvent(document.body, 'mousemove', function (e) {
         if(self.moveNode) self.moveNode.doResize(e);
      });
   },

   resizePoint: function(e, elm) {
      var offset = Position.offset(elm);
      var page   = Position.page(e);

      offset.y += elm.offsetHeight;
      offset.x += elm.offsetWidth;

      if(offset.y - 32 < page.y && page.y < offset.y &&
         offset.x - 32 < page.x && page.x < offset.x - 8) {
         return true;
      }
   },

   doResize: function(e, elm) {
      var offset = Position.offset(elm);
      var page   = Position.page(e);

      var width  = page.x - offset.x + 24;
      var height = page.y - offset.y + 16;
      if (width  < 50) width  = 50;
      if (height < 50) height = 50;

      elm.style.height = height + 'px';
      elm.style.width  = width  + 'px';
   }
}

ElementResizer._ChildElement = function() {
   this.initialize.apply(this, arguments);
}

ElementResizer._ChildElement.prototype = {
   initialize: function(base, elm) {
      this.base = base;
      this.elm  = elm;
   },

   resizePoint: function(e) {
      return this.base.resizePoint(e, this.elm);
   },

   doResize: function(e) {
      return this.base.doResize(e, this.elm);
   }
}

var Position = {
   offset: function(elm) {
      var pos = {};
      pos.x = this.getOffset('Left', elm);
      pos.y = this.getOffset('Top', elm);
      return pos;
   },

   getOffset: function(prop, el) {
      if(!el.offsetParent || el.offsetParent.tagName.toLowerCase() == "body")
         return el['offset'+prop];
      else
         return el['offset'+prop]+ this.getOffset(prop, el.offsetParent);
   },

   page: (document.all) ?
      (function() {
         var pos = {};
         pos.x = event.x + (document.body.scrollLeft || document.documentElement.scrollLeft);
         pos.y = event.y + (document.body.scrollTop  || document.documentElement.scrollTop);
         return pos;
      })
      :
      (function(e) {
         var pos = {};
         pos.x = e.pageX;
         pos.y = e.pageY;
         return pos;
      })
}

var addEvent = (window.addEventListener) ?
   (function(elm, type, event) {
      elm.addEventListener(type, event, false);
   }) : (window.attachEvent) ?
   (function(elm, type, event) {
      elm.attachEvent('on'+type, event);
   }) :
   (function(elm, type, event) {
      elm['on'+type] = event;
   }) ;

ここまでが必須部分で、以下がリサイズする要素の指定。このまま使えばページ内の全 TEXTAREA がリサイズ可能になる。

addEvent(window, 'load', function() {
   var textareas = document.getElementsByTagName('textarea');

   for(var i = 0;elm = textareas[i];i++) {
      (function(elm) {
         var obj = ElementResizer.add(elm);
         var cursor = false;

         addEvent(elm, 'mousemove', function (e) {
            if(!cursor && obj.resizePoint(e)) {
               elm.style.cursor = 'se-resize';
               cursor = true;
            } else if(cursor && !obj.resizePoint(e)) {
               elm.style.cursor = 'default';
               cursor = false;
            }
         });
      })(elm);
   }

   ElementResizer.start();
});

ElementResizer って名前が何かのライブラリと被りそうだなぁ。_ChildElement とかほんとに必要なのか?ってくらい無駄に長くなってる印象があるけど、良くわかんない、考えるの面倒くさい。

* 更新履歴

  • 2007-03-29 - XHTML 対応
  • 2006-08-28 - Opera9 対応

Posted by Kyosuke Takayama at 2006-08-25 (Fri) 17:59 printable version

この記事へのコメント

1) あsdf (2006-08-30 (Wed) 09:05)

ソースは見てませんが、同じような動作をするものが思い当たったので一応報告。

「JKL.Resizable - サイズ可変エレメント」でGoogle検索。(URL貼れないので)

2) takayama (2006-08-30 (Wed) 16:43)

www.kawa.net/works/js/jkl/resizable.html

へー、縦だけとか横だけの可変にも対応してますね。

はてなの日記編集画面でも縦方向が可変になるようだし意外とあるみたいですね。

コメントはお気軽にどうぞ

Cookie に保存しますか?


・スパム対策のため、http:// を含むコメントの投稿は出来ません。
・スパムチェックのため、投稿がすぐに反映されない場合があります。
・メールアドレス入力欄には何も入力しないでください。

トラックバック

トラックバックURL: http://espion.just-size.jp/mt-tb.cgi/602

鷹の島: JavaScript の人気に嫉妬 (2006-08-28 (Mon) 16:02) 0%

テキストエリアのリサイズネタ が思った以上に好評でウハウハなんですけど、Opera が怪しいとか Safari で動かんって事なので、とりあえず Opera の対応をしてみました。Safari はちょい待ち。 どうやら Opera では(テキストエリアの)スクロールバー上で mouseup のイベン...



この記事のリンク元

 
Copyright (C) Kyosuke Takayama, All rights reserved.