Mochikitも好きですが、普段はRails使いということもあってprototype.jsを使っています。

そういえばjavascriptのライブラリでOOなもの、ということで初めて出会ったのは jsolait でした。 当時の印象としては「んー確かにがんばってるんだけど・・・ちょっと大げさっていうか・・・」って感じでした。

そして去年、prototype.jsに出会うわけですが「class-style OO」とうたっている部分がかなりシンプル(すぎ)で衝撃でした。

ただ、やっぱりjavascriptにおいて「継承」というのはやっかいな問題です。 というわけで誰か作ってると思うんですが、より簡単に継承できるライブラリを作ってみました。

Class.def = function(definition) {
  var klass = Class.create();
  if(definition.__extend__)
    Class.inherit(klass, definition.__extend__);
  if(definition.__static__)
    Object.extend(klass, definition.__static__);
  if(definition.__include__) {
    if(definition.__include__.constructor != Array)
      definition.__include__ = [definition.__include__];
    definition.__include__.each(function(include){
      Object.extend(klass.prototype, include);
    });
  }
  ["__static__","__extend__","__include__"].each(function(n){delete definition[n];}
  Object.extend(klass.prototype, definition);
  return klass;
}    

Class.inherit = function(child, parent) {
  Object.extend(child, parent);
  child.__super__ = parent.prototype;
  var dummy = function(){};
  dummy.prototype = parent.prototype;
  child.prototype = new dummy();
  child.prototype.constructor = child;
  return child;
}

こんだけです。 使い方はサンプルをみるほうがわかりやすいと思うので、サンプルをどーぞ。

var IncludedClass = Class.def({
  __static__ : {
    includedMethod : function() {
      return "includedMethod:"+this.value;
    }
  }
});    

var AClass = Class.def({__include__ : IncludedClass,
  __static__ : {
    A : "A static"
  },

  initialize : function(val) {
    if(!val) throw "error";
    this.val = val;
    this.klass = "AClass";
  },

  inspect : function() {
    return "< "+this.klass+" : "+this.val+">";
  }
});

var BClass = Class.def({ __extend__ : AClass,
  __static__ : {
    B : "B static"
  },

  initialize : function(val) {
    BClass.__super__.initialize.call(this, val);
    this.klass = "BClass";
  }
});

var CClass = Class.def({ __extend__ : BClass,
  __static__ : {
    C : "C static"
  },

    initialize : function(val) {
      CClass.__super__.initialize.call(this, val);
      this.klass = "CClass";
    }
});

var a = new AClass("aaaaaaa");
var b = new BClass("bbbbbbb");
var c = new CClass("ccccccc");
alert("a inspect:"+a.inspect()); //=> a inspect:
alert("b inspect:"+b.inspect()); //=> b inspect:
alert("c inspect:"+c.inspect()); //=> c inspect:
alert("includedMethod:"+a.includedMethod()); //=> includedMethod:included aaaaaa
alert("CClass.A:"+CClass.A); //=> CClass.A:A static
alert("CClass.B:"+CClass.B); //=> CClass.B:B static
alert("CClass.C:"+CClass.C); //=> CClass.C:C static
alert("b.constructor = a.constructor:"+(b.constructor == a.constructor).toString()); //=>b.constructor = a.constructor:false
alert("b instanceof BClass:"+(b instanceof BClass).toString()); //=>b instanceof BClass:true
alert("b instanceof AClass:"+(b instanceof AClass).toString()); //=>b instanceof AClass:true
alert("c instanceof BClass:"+(c instanceof BClass).toString()); //=>c instanceof BClass:true
alert("c instanceof AClass:"+(c instanceof AClass).toString()); //=>c instanceof AClass:true</div>

継承の処理がかなり楽になっていると思います。 テキトーに場当たりで単純にnewを使って継承していたりすると

「親クラスのコンストラクタに必須な引数があって、それがないとエラーでるから継承できねーよ、しゃーない適当に引数付けとくか」

ということになったりするもんですが(俺はよくなってますw)このライブラリを使えば大丈夫。 また、こんな変な書き方イヤだよ!!って方でも継承の部分はClass.inheritに独立させてあるのでそこだけつかえばオッケーです。

一応動作は確認していますがおかしいところあったら報告していただけるとありがたいです。


naoyaさんTinyMCE について書かれていますが、僕も以前使ったことがあります。 WYSYWIG な HTML エディタということでは、僕はこのページでも使ってるFCKeditorがオススメです。(実は昔TinyMCEからサーバーに日本語送った時に化けることがあったので(UTF-8で)それ以来FCKeditorなんですけど今はどうなんだろう・・・)

こちらもTinyMCEと同じく

  • JavaScript で記述された
  • LGPL でオープンソースな
  • クロスプラットフォームの
  • 多言語対応もしてて
  • 簡単に使える

ライブラリなんです。かなり使いやすいですよ。

導入も簡単です。typoの場合、

<script src="http://inforno.net/FCKeditor_install_path/fckeditor.js" type="text/javascript"></script>
<script language="javascript">
Event.observe(window, "load", function(){
  var list = ["article_extended", "article_body"];
  for(var i=0,l=list.length; i < l; i++) {
    var fck = new FCKeditor(list[i]);
    fck.BasePath = "FCKeditor_install_path";
    fck.Config["CustomConfigurationsPath"] = fck.BasePath + "myconfig.js";
    fck.Height = 400;
    fck.ReplaceTextarea();
  }
});
</script>[/js]

こんな感じで初期化しています。IDを指定してこのtextareaを、というのも簡単ですね。

image

海外ではAPIを使ったデスクトップクライアントが結構人気みたいですけど、日本じゃあんまり使ってる人聞かない・・・Typoもデフォルトはデスクトップクライアント使え!みたいな感じなんですけどFCKeditorで一件落着。便利便利。