FuelPHPで軽量ビジュアルエディタの設置(実践編その10)

今日は、ブログサイト等を作るときに文字装飾を簡単にしてくれるビジュアルエディタをFuelPHPに設置する方法を調べてみたいと思います。只、ビジュアルエディターをサイトに設置するとセキュリティリスクが発生しますので、管理者ページや会員専用ページ等でのみ使用するようにして下さい。今回もCollectionコントローラを修正しながら、作成していきますので、分からない箇所は、遡って調べて下さい。

CLEditor

1. まず最初にCLEditorというビジュアルエディタを設置してみたいと思います。下記サイトからCLEditor Version1.3.0のZipファイルをダウンロードします。

http://premiumsoftware.net/cleditor/

2. ダウンロードしたファイルを解凍します。3つのファイル(jquery.cleditor.css、jquery.cleditor.js、jquery.cleditor.min.js)とimagesフォルダがあります。

3. まず、cssファイル(jquery.cleditor.css)をpublic/assets/cssフォルダの中にコピーします。

4. 次に、2つのjsファイル(jquery.cleditor.js、jquery.cleditor.min.js)をpublic/assets/jsフォルダの中にコピーします。

5. 最後に、imagesフォルダごと、public/assets/cssフォルダにコピーします。既にcssフォルダにimagesフォルダを作成している人(jquerymobile関連の画像が入っている人)は、中の2つの画像をimagesフォルダの中に保存します。

6. それでは、テンプレートファイルを作成します。下記に記述例を表示します。今回は、入力フォームの時だけ、CLEditorを適用するように設定してみました(12行目)。

app/views/template.php

<!DOCTYPE html>
 <html>
 <head>
 <meta charset="utf-8">
 <title><?php echo $title; ?></title>
 <meta name="viewport" content="width=device-width,minimum-scale=1">
 <?php echo Asset::css('bootstrap.min.css');?>
 <?php echo Asset::css('bootstrap-responsive.min.css');?>
 <?php echo Asset::js('jquery-1.7.2.min.js');?>
 <?php echo Asset::js('bootstrap.min.js');?>
 <!--入力フォームの時だけ適用する-->
 <?php echo isset($editor) ? $editor : '' ;?>
 <!--自分専用スタイルシート-->
 <?php echo Asset::css('my-style.css');?>
 </head>
 <body>
 <div class="navbar">
 <div class="navbar-inner">
 <div class="container">
 <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
 <span class="icon-bar"></span>
 <span class="icon-bar"></span>
 <span class="icon-bar"></span>
 </a>
 <?php echo Html::anchor('collection/index/',$title,array('class'=>'brand'))?>
 <div class="nav-collapse">
 <ul class="nav">
 <li><?php echo Html::anchor('collection/add/','新規作成')?></li>
 <li><?php echo Html::anchor('winauth/logout/','ログアウト')?></li>
 <?php if(Auth::member(100)):?>
 <li><?php echo Html::anchor('winauth/admin/','管理室へ')?></li>
 <?php endif;?>
 <form class="navbar-search pull-left">
 <input type="text" class="search-query" placeholder="Search">
 </form>
 </ul>
 </div>
 </div><!--/nav-->
 </div><!--/navbar-innner-->
 </div><!--/navbar-->
 <div class="container">
 <div id="header">
 <!--ヘッダーがあれば表示する-->
 <?php echo isset($header) ? $header : '' ;?>
 </div><!--/header-->
 <div class="row" id="content">
 <div class="span4" id="sidebar">
 <!--サイドバーがあれば表示する-->
 <?php echo isset($sidebar) ? $sidebar : '' ;?>
 </div><!--/span4-->
 <div class="span8">
 <!--ここにコンテンツを表示します。-->
 <?php echo $content; ?>
 </div><!--/span8-->
 </div><!--/content-->
 <div id="footer" style="background-color:yellow; text-align: center;">
 <p>copyright(c)2012 WinRoad徒然草</p>
 <p>表示速度{exec_time}s 使用メモリ{mem_usage}mb</p>
 </div><!--/footer-->
 </div><!--/container-->
 </body>
 </html>

7. ビューファイルeditorを下記のように記述します。スクリプトは、id=”editor”の箇所にcleditorを適用するという単純なものです。これが上のテンプレートファイルの12行目に代入されます。

app/views/collection/editor.php

<?php echo Asset::css('jquery.cleditor.css');?>
 <?php echo Asset::js('jquery.cleditor.min.js');?>
 <script type="text/javascript" src="jquery.cleditor.min.js"></script>
 <script type="text/javascript">
 $(document).ready(function() {
 $("#editor").cleditor();
 });
 </script>

8. ビューファイルのadd.phpとedit.phpを下記のように記述します。ほとんど変更していません。実際に変更したところは、テキストエリア部分のidをeditorにしただけです。add.php、edit.php共に27行目です。

app/views/collection/add.php

<h3>新規作成</h3>
 <?php echo Form::open(array('name'=>'add','method'=>'post')); ?>
 <?php echo '<div class="alert-error">'.Session::get_flash('error').'</div>'?>
 <table width="100%" border="0">
 <tr>
 <th align="right" scope="row">タイトル:</th>
 <td class="input"><?php echo Form::input('title', Input::post('title', isset($collection) ? $collection->title : ''), array('class' => 'span6')); ?>
 &nbsp;</td>
 </tr>
 <tr>
 <th align="right" scope="row">種別:</th>
 <td><?php echo Form::select('col_assort_id', null,$assorts,array('class'=>'span3')); ?>
 &nbsp;</td>
 </tr>
 <tr>
 <th align="right" scope="row">コード番号:</th>
 <td><?php echo Form::input('col_code', Input::post('col_code', isset($collection) ? $collection->col_code : ''), array('class' => 'span6')); ?>
 &nbsp;</td>
 </tr>
 <tr>
 <th align="right" scope="row">保管場所:</th>
 <td><?php echo Form::input('save_space', Input::post('save_space', isset($collection) ? $collection->save_space : ''), array('class' => 'span6')); ?>
 &nbsp;</td>
 </tr>
 <tr>
 <th align="right" scope="row">備考:</th>
 <td><?php echo Form::textarea('note', Input::post('note', isset($collection) ? $collection->note : ''), array('id'=>'editor')); ?>
 &nbsp;</td>
 </tr>
 <tr>
 <th colspan="2" scope="row">
 <?php echo Form::submit('submit', '保存', array('class' => 'btn btn-primary span4')); ?>
 </th>
 </tr>
</table>
 <?php echo Form::close(); ?>

app/views/collection/edit.php

<h3>データ更新</h3>
 <?php echo Form::open(array('name'=>'edit','method'=>'post')); ?>
 <?php echo '<div class="alert-error">'.Session::get_flash('error').'</div>'?>
 <table width="100%" border="0">
 <tr>
 <th align="right" scope="row">タイトル:</th>
 <td class="input"><?php echo Form::input('title', Input::post('title', isset($collection) ? $collection->title : ''), array('class' => 'span6')); ?>
 &nbsp;</td>
 </tr>
 <tr>
 <th align="right" scope="row">種別:</th>
 <td><?php echo Form::select('col_assort_id',$collection->col_assort_id,$assorts,array('class'=>'span3')); ?>
 &nbsp;</td>
 </tr>
 <tr>
 <th align="right" scope="row">コード番号:</th>
 <td><?php echo Form::input('col_code', Input::post('col_code', isset($collection) ? $collection->col_code : ''), array('class' => 'span6')); ?>
 &nbsp;</td>
 </tr>
 <tr>
 <th align="right" scope="row">保管場所:</th>
 <td><?php echo Form::input('save_space', Input::post('save_space', isset($collection) ? $collection->save_space : ''), array('class' => 'span6')); ?>
 &nbsp;</td>
 </tr>
 <tr>
 <th align="right" scope="row">備考:</th>
 <td><?php echo Form::textarea('note', Input::post('note', isset($collection) ? $collection->note : ''), array('class' => 'span6', 'rows' => 8,'id'=>'editor')); ?>
 &nbsp;</td>
 </tr>
 <tr>
 <tr>
 <th colspan="2" scope="row">
 <?php echo Form::submit('submit', '保存', array('class' => 'btn btn-primary span4')); ?>
 </th>
 </tr>
</table>
 <?php echo Form::close(); ?>

9. 最後にコントローラのaddアクションと、editアクション、明細ページ表示のdetailアクションを下記のように記述します。変更箇所は、addアクションの46行目とeditアクションの42行目に、cleditorを使うためのヘッダー情報を渡す記述をしたことと、detailアクションの11行目にビューにデータを渡すときにエスケープ処理をしないように第3引数にfalseを指定しているだけです。

app/classes/controller/collection.php

public function action_add($id=null){
 //もしPOST送信されたら
 if (Input::method() == 'POST'){
 $val = Model_Collection::validate('add');

 if ($val->run())
 {
 $collection = Model_Collection::forge(array(
 'title' => Input::post('title'),
 'created' => date('Y-m-d H:i:s'),
 'modified' => date('Y-m-d H:i:s'),
 'col_code' => Input::post('col_code'),
 'save_space' => Input::post('save_space'),
 'col_assort_id' => Input::post('col_assort_id'),
 'picture_id' => Input::post('picture_id'),
 'note' => Input::post('note'),
 ));

 //もしデータが保存されたら
 if ($collection and $collection->save())
 {
 Session::set_flash('success', '<span class="btn btn-primary span8">ID-'.$collection->id.'の『'.$collection->title.'』を追加しました</span><br>');
 //indexページへ移動
 Response::redirect('collection/index');
 }
 else //データが保存されなかったら
 {
 Session::set_flash('error', '保存できませんでした');
 }
 }
 else //バリデーションNGなら
 {
 Session::set_flash('error', $val->show_errors());
 }
 }
 //モデルColassrotからデータを取得
 $colassorts=Model_Colassort::find('all');
 foreach($colassorts as $row):
 //id番号をキーにして配列assortsを作成
 $data['assorts'][$row->id]=$row->as_name;
 endforeach;
 //テンプレートファイルにデータの引き渡し
 $this->template->title="WinRoad徒然草";
 //テンプレートファイルにデータを引き渡す
 $this->template->content = View::forge('collection/add',$data);
 $this->template->editor=View::forge('collection/editor');
 }
public function action_edit($id){
 //もしPOST送信されたら
 if (Input::method() == 'POST'){
 //バリデーションのインスタンス化
 $val=Model_Collection::validate('edit');
 //バリデーションOKなら
 if($val->run()){
 //モデルに値をセット
 $collection=Model_Collection::find($id);
 $collection->title=Input::post('title');
 $collection->col_assort_id=Input::post('col_assort_id');
 $collection->modified=date('Y-m-d H:i:s');
 $collection->col_code=Input::post('col_code');
 $collection->save_space=Input::post('save_space');
 $collection->note=Input::post('note');
 //もしデータが保存されたら
 if ($collection and $collection->save()){
 //セッションフラッシュのセット
 Session::set_flash('success', '<span class="btn btn-primary span8">ID-'.$collection->id.'の『'.$collection->title.'』を更新しました</span><br>');
 //indexページへ移動
 Response::redirect('collection/index');
 }else {
 //データが保存されなかったら
 Session::set_flash('error', '保存できませんでした');
 }
 } else {
 //バリデーションNGなら
 Session::set_flash('error', $val->show_errors());
 }
 }
 //指定idのデータを取得
 $data['collection']=Model_Collection::find($id);
 //モデルColassrotからデータを取得
 $colassorts=Model_Colassort::find('all');
 foreach($colassorts as $row):
 //id番号をキーにして配列assortsを作成
 $data['assorts'][$row->id]=$row->as_name;
 endforeach;
 //テンプレートファイルにデータの引き渡し
 $this->template->title="WinRoad徒然草";
 $this->template->editor=View::forge('collection/editor');
 $this->template->content = View::forge('collection/edit', $data);
 }
public function action_detail($id){
 //idが送信されたら
 if(Input::method() == 'GET'){
 //SQLの発行
 //$query=DB::select()->from('collections')->where('id',$id)->execute();
 $data['col']=Model_Collection::find($id);
 $data['img']=Model_Colimage::find('last',array('where'=>array('collection_id'=>$id),'order_by'=>array('created'=>'desc')));
 //テンプレートファイルにデータの引き渡し
 $this->template->title="WinRoad徒然草";
 //ビューファイルの呼び出し
 $this->template->content=View::forge('collection/detail',$data,false);
 }
 }

10. それではブラウザで確認してみます。新規入力をクリックするとCLEditorが起動しているのが分かります。文字装飾をして保存してみます。

11. 明細ページを開けば、先程保存したとおりの文字装飾で表示されています。

NicEdit

12. 次に軽量コンパクトで定評のあるNicEditを設置してみます。まず、公式サイトのダウンロードページへ行きます。

http://nicedit.com/download.php

13. 必要なオプションにチェックを入れ、『Download』ボタンをクリックします。

14. demosフォルダ以外に2つのファイルがあるだけです。

15. この2つのファイルをpublic/assets/jsフォルダにコピーします。

16. ヘッダー情報を記述したファイルeditor.phpを下記のように書き換えます。

app/views/collection/editor.php

<?php echo Asset::js('nicEdit.js');?>
 <script type="text/javascript">
 bkLib.onDomLoaded(nicEditors.allTextAreas);
 </script>

17. NicEditはidで、適用するテキストファイルを指定するのではなくて、textera全てに適用されます。これで表示されるだろうと思い、ブラウザで確認してみたところ、アイコン画像が表示されていませんでした。

18. あれこれ調べて(アイコン画像の保存先を色々変更して)みたのですが、全く表示されません。仕方なくnicEdit.jsファイルをいじることにしました。31行目を下記のように修正しました。ドメイン名は各自に合わせて記述して下さい。

pubic/assets/js/nicEdit.js

 iconsPath : 'http://ドメイン名/public/assets/js/nicEditorIcons.gif',

19. これでアイコン画像が表示されるようになりました。

20. CLEditorはMITライセンス、又は、GPLライセンスです。NicEditはMITライセンスです。両方とも、ライセンスは余り気にせずに比較的容易に導入出来ると思います。

21. 高機能エディタのCKEditorやTinyMCEの設置方法も調べてみたいのですが、CKEditorはライセンスが複雑ですので、導入には躊躇しています。一応ソースコードに手を加えないでそのまま利用するのなら、商用利用も可能と考えていいのかとは思いますが、ライセンス関係はデリケートですので、慎重に検討しないといけません。ライセンス的に大丈夫そうでしたら、CKEditorとTinyMCEの両方の設置方法も調べてみたいと思います。

とりあえず、今回はこれで、自作のブログの投稿ページが簡単に装飾出来るようになりました。CLEditor及びNicEditの使い方は公式サイトをご覧下さい。

本日は、以上です。

追伸

NicEditですが、試してみたらCDNでも使えるみたいです。editor.phpを下記のように修正するだけで、ファイルを何もダウンロードしなくても使うことが出来ます。

app/views/collection/editor.php

<script type="text/javascript" src="http://js.nicedit.com/nicEdit-latest.js"></script>
 <script type="text/javascript">
 bkLib.onDomLoaded(function() { nicEditors.allTextAreas() });
 </script>

画像の保存先が分からず、あれこれ悩んだのは、何だったのでしょう。以上、追伸でした。

このエントリーを含むはてなブックマーク Buzzurlにブックマーク livedoorクリップ Yahoo!ブックマークに登録

トラックバック&コメント

この投稿のトラックバックURL:

コメントをどうぞ

このページの先頭へ