CLEditor 探索:まとめ

テキストエリアをWISYWIGエディタに変えるCLEditor の秘密を解くためにソースを読んできたが、少々細部に入りすぎたため見通しが悪くなった。ブログ上で完全解読するのは無理があるので、最後にもう一度CLEditor のソースの概要をまとめて一連の記事の終わりとしたい。

テキストエリアをエディタにする仕掛けの大まかなアイディアについては、前回までの記事で、テキストエリアのまわりにdiv 要素の塊であるエディタのオブジェクトを作成することであるのが明らかにできたと思うので、後はその構想にそってソースを解読することができるだろう。

ソースを解読する上で知りたいことは数多くある。デフォールトオプションをどのようにユーザオプションでカスタマイズするのか、div 要素の階層構造であるエディタオブジェクトの本体をどのようにアプリケーションの画面に整形することができるのか、ボタンを表す div 要素のイベントをどのようにイベントハンドラで処理するのか、プラグインをクロージャでカプセル化する際に、インスタンスメソッドや、大域変数などの参照を可能にするにはどのようにすればよいのか等々、技術的な問題についてはまだ手つかずの状態だが、これらを全てブログで記事にするのは少し荷が重い。

今回の記事の目的は、CLEditor プラグインの、名前空間をほとんど消費せずにテキストエリアという単純な引数から複雑な機能のWISYWIGエディタを作り出せるのかという疑問を解くことだったので一応の終了としたい。


CLEditor のソースの概要

(function($) {

==========
jQuery Plugin
==========

$.cleditor = {

    //全ての新しい cleditor インスタンスで使われるデフォールトを定義する。


    defaultOptions: {
        width: .. ,
        hight: .. ,
        contorls: .. ,
        colors: .. ,
        fonts: .. ,
        sizes: .. ,
        styles: .. ,
        useCSS: .. ,
        docType: .. ,
        docCSSFile: .. ,
        bodyStyle: ..
    },

//全ての利用可能なツールバーのボタンの属性を定義する。init の文字列に記述されたボタンの属性は cleditor の初期化の際にボタンオブジェクトに変換されそれぞれのボタンの属性が設定される。
例: buttons.size.title = "Font Size"

    buttons: { init: "bold,,| italic,,| ... " },

    //イメージパス - イメージ・フォルダのパスを返す

    imagePath: function() { return imagesPath(); }
};

//cleditor - 検索されたテキストエリアについて新しいエディタ(オブジェクト)を作成する。

$.fn.cleditor = function(options) {

    //エディタオブジェクトを納めるための新しい配列型のjQuery オブジェクトを生成する。
    var $result = $([]);

    全てのクエリにマッチするテキストエリアについてエディタオブジェクトを生成し、jQuery オブジェクト $result に納めて戻り値として返す。

    return $result;
};

====================
Private Variables
====================

省略

=================
Initialization
=================

//$.cleditor.buttons.init の文字列をボタンオブジェクトに変換して、init の文字列は消去する。

$.each(buttons.init.split("|"), function(idx,button) { ... });
delete buttons.init

=============
Constructor
=============

//cleditor 関数はテキストエリアを引数としてとり、エディタオブジェクトを生成する。

cleditor = function(area, options) {

    デフォールトのオプションを取得し、引数のオプションでオーバーライドする。
    テキストエリアを隠し、エディタオブジェクトと関連付ける。
    メインのコンテナを生成し、テキストエリアを納める。
    ツールバーを生成して、メインのコンテナに納める。
    最初のグループをツールバーに納める。

    //ボタンをひとつづつツールバーに納めていく。options.controls の文字列に記載された順番にしたがう。

    $.each(options.controls.split(" "), function(idx, buttonName) {
        ボタン名がない場合の処理
        ボタン名が"|"の場合の処理
        一般のボタンの場合の処理
    });

    // メインコンテナのdiv要素をテキストエリアの前に挿入し、テキストエリアはその中に移動させる。

    $main.insertBefore($area)
    .append($area);

    document click イベント・ハンドラをバインドする。
    ウィンドウのリサイズに対応する処理をする。

    HTML文書をレンダリングするための iframe を生成しコントロールをリサイズする。
    refresh(editor);
};

================
Public Methods
================

cleditor のインスタンスメソッドを cleditor プラグインのクロージャの外から使えるようにする。

================
Event Handlers
================

//イベントハンドラを記述する。

function buttonClick(e) {

    ボタンが disable かどうかチェックする。
    ボタンクリックイベントを発生する(通常のボタンの処理)。
    トグル・ソースボタンの処理。
    リッチテキストモードの処理。
    ペーストの処理。
    プリントの処理。
}

====================
Private Funcitons
====================

//cleditor で内部的に使用する様々の関数の記述。

function checksum(text) { ... }
function clear(editor) { ... }
function createPopup(popupName, options popupTypeClass, popupContent, popupHover) { ... }
function disable(editor, disabled) { ... }
function execCommand(editor, command, value, useCSS, button) { ... }
function focus(editor) { ... }
function getRange(editor) { ... }
function getSelection(editor) { ... }
function hex(s) { ... }
function hidePopups() { ... }
function imagesPath() { ... }
function imageUrl(filename) { ... }
function refresh(editor) { ... }
function refreshButtons(editor) { ... }
function restoreRange(editor) { ... }
function select(editor) { ... }
function selectedHTML(editor) { ... }
function selectedText(editor) { ... }
function showMessage(editor, message, button) { ... }
function showPopup(editor, popup, button) { ... }
function sourceMode(editor) { ... }
function updateFrame(editor, checkForChange) { ... }
function updateTextArea(editor, checkForChange) { ... }

}) (jQuery);
[PR]
by tnomura9 | 2011-01-09 21:49 | JavaScript | Comments(10)
Commented by 吉田 at 2011-02-18 15:11 x
すいません。さっき非公開でコメントしてしまいましたので、もう一度投稿します。


こんにちは、吉田と申します。
CLEditorを使っていてうまくいかないところがあり、tnomura9さんが
かなり詳しく調べられてると拝見しまして、
筋違いとは思いますが質問させていただきます。
教えていただけませんでしょうか。
CLEditorの設置はうまくいったのですが、そのtextareaの内容を消したり、値をセットしようとすると
textareaにはセットできているのですが、CLEditorには反映されません。
何か方法があるのでしょうか?それとも設置がうまくいっていないのでしょうか。
よろしくお願いいたします。
Commented by tnomura9 at 2011-02-18 21:54
吉田さん、コメントありがとうございました。
このブログのjQueryデモで紹介したCLEditorのデモでは、右端の
表示切替ボタンをクリックすると、テキストエリアに入力したソースを
レンダリングするようです。お尋ねの状況が掴めていないのですが、
textarea のソースをインラインフレームにレンダリングするのに、
private function の updateFrame() が使われているようです。
このupdateFrame() の実行の段階で、textarea の内容の変更
がリジェクトされているのではないでしょうか。updateFrame() の
記述はCLEditor のソースの終わりの方にあるので見つけやすいと
思います。CLEditor のソースを最後まできちんと解読したわけでは
ないので明確なお答えができず申し訳ありません。
Commented by 吉田 at 2011-02-19 00:57 x
tnomura9さん、お返事ありがとうございます。
たとえば実際にプログラムで使う場合に、登録したデータを修正するような画面では修正対象のデータをtextareaに表示させてユーザーに修正させるということになるでしょうし、新たに登録画面を開くときにはtextareaをクリアして空の状態にすると思うのですが、その時は普通にhtmlのtextareaタグに対して値をセットしたり、空文字をセットすればCLEditorのほうに反映されるのでしょうか?
updateFrame() というprivate functionは、外部から呼び出す必要があるのでしょうか?
「リジェクト」というのがわからないのですが・・。
私もCLEditorのソースを読まないとダメですよね・・。
ライブラリの使い方がいまいちわかってないです。
Commented by tnomura9 at 2011-02-19 09:33
吉田さん、コメントありがとうございました。
CLEditorをプログラムで操作する方法は、私も知らないのですが、
その方法としては、CLEditor オブジェクトをコンストラクタで生成する
ときに、変数にオブジェクトへの参照を取得する必要があるとおもいま
す。
ソースをざっと読み返した限りでは、コンストラクタからオブジェクトへ
の参照は取得可能です。また、updataFrame()関数は、インスタン
スメソッドとして利用可能のようですのでそれを利用すればよいと思わ
れます。
CLEditor をプログラムからコントロールすることは考えていなかった
ので詳しいことはソースを解読する必要があると思いますが、結構
大変なのでこの場で回答できるか自信がありません。
もう一度ソースにチャレンジしたいと思います。
CLEditor のソースについては解読をおすすめします。update-
Frame 関数の中でも、チェックサムをとったり、スクリプト・インジェ
クション対策をしたりなど、ネットの入力を受ける際はそれなりの
対策をしないといけないのだなと思わせる記述があるので参考に
なると思います。
Commented by 吉田 at 2011-02-19 19:10 x
ご丁寧な回答ありがとうございます。
やはりインスタンスを生成してメソッドを利用するんですね。Ext jsというライブラリでリッチテキストエディタを使ったときははあまり意識しなくてもできていたので、こっちもそうかなと思ったのですが・・。
勉強のためにも私も解析がんばってみます。
Commented by tnomura9 at 2011-02-20 06:10
吉田さん、コメントありがとうございました。
ちょっと試してみたのですが、CLEditor のエディタインスタンスを生成
するときに、次のようにして変数 editor に参照を取得し、

editor = $('input').cleditor();

次のようにテキストエリアに書き込んで、

editor[0].$area.text('<h1>hello, world</h1>');

updateFrame メソッドを呼び出したら表示できました。

editor[0].updateFrame();

変数editor にはエディタオブジェクトではなく、エディタオブジェクトの
配列が入るようです。
勉強になりました。コメントありがとうございました。
Commented by 吉田 at 2011-02-20 17:12 x
私も同じようにしてできました。
オブジェクトが配列になっているのがミソですね。
.clear()などのメソッドも同様に使えました。
ありがとうございました!
Commented by 新家 at 2018-03-29 22:31 x
cleditor()[0].sourceMode() で、どのモードなのかは、わかるのですが、ソース内に画像にボーダーなどの CSS を設定するためには、テキストモードにする必要があります。
編集モードでは、画像の URL だけとなり、使えません。
編集モードから、テキストモードに一時的に変更し、また、音に戻すことができれば、と。
そんなことは可能でしょうか。
オリジナルのソースを見ましたが、よくわかりません。
よろしく、おねがいします。
Commented by 新家 at 2018-03-30 10:03 x
ソースを見直して、問題の箇所を発見し、自己解決しました。
その部分を掲載できません、ね。
Commented by tnomura9 at 2018-03-30 10:19
> 新家さん、コメントありがとうございました。
Creditorを触ったのはずいぶん前で、今はご指摘の箇所がどこかも
理解できない状態です。解決されたとのことで安心しました。
修正部分の掲載は望ましいと思いますが、上に述べた状態なので
申し訳ありません。
<< jQuery UI の使い方 CLEditro 探索:Add... >>