ブラウザで使うWYSIWYGエディターを作るときのcreateRangeとかselectionなんかの処理
WordPressでこうして記事を書く時に、文字色を変えたりできるエディターを使いますが、簡単なものなら自作する事も可能です。また、多くの方が有償・無償でWYSIWYGエディターやリッチテキストエディターを作成・公開しています。
TinyMCEが有名でしょうか、ただ、商用だとライセンスの問題が出てきます。MITライセンスのものも有りますが、一番欲しい画像アップロード機能が無くがっくりくることも。
お客さんってたいがい、記事を書くのと画像をアップロード出来る、これを求めますので、ここは抑えておきたいポイントですよね。あと機能過多で使わないものが多く、削るのが面倒です。
で、人のを借りるのも癪だし高いライセンス料を払いたくないですし、どうせなら機能を限定して導入し易いものを作ればオープンソースにも導入し易いだろうなぁと思い、テスト用のとってもちゃちぃ(←方言?)ものを作ってみました。
一応はIE8以上対応って事で書いています。そう、IEくん、君だよ君
この、古参大手シェア大なブラウザさえ無ければ、どれだけのWEBデザイナーさんの労力が軽くなる事か。新しいバージョン出す度に開発者の足を引っ張るIEくん、ほんとどうにかなりませんでしょうか。
さて、WYSIWYGエディターの話しに戻します。
そもそもWYSIWYGエディターってどういう仕組なのか
iframeってご存知でしょうか?最近は使う機会が減りましたが、iframeの中に別なページを表示出来るので、サイドバーナビゲーションなんかによく使われていたHTMLタグです。で、このiframのデザインモードをONにする事で編集出来るようになります。
デザインモードをONにする
/* * iframのデザインモードをONにする */ doc = document.getElementById('iFrameName').contentDocument; doc.designMode = "On";
これだけで編集する事が出来るようになります。
で、ボタンを作って押したときに下のようなコマンドを実行すると、文字を太くしたり出来ます。
execCommand('bold', false, null);
このコマンドを実行する為のトリガーにbutton以外は使わない方が吉。画像とかAタグで格好良く決めたい!と思っても、IEだと別の場所をクリックしたりするだけで、選択した文字のフォーカスが外れてしまうのです(selectは大丈夫そう)
なので、ボタンを押すだけで実行出来る、太字とか斜体とか取り消し線などの処理はボタンで配置し、背景に画像なんかを指定して並べると良いと思います。
IEでフォーカスが外れる!ほんと要らないコ・・・・
さて、ボタン一発で済まない処理、例えば選択した文字にURLを指定してリンクにしたいといったケースです。これは文字を選択した後にURLを入力しようとすると、IEは選択した文字のフォーカスが外れてしまい、どこにAタグを指定すれば良いのか解らなくなってしまいます。
なので、フォーカスした位置を記憶して、処理を終えたらフォーカスを戻すって処理をする事になります。
何か操作したときにフォーカスの位置を記録する
これをリンク挿入ボタンを押したときに実装します。それぞれ、変数に代入しておきます。
var set_sel = null; var set_range = null; function getRange(){ var sel = win.getSelection ? win.getSelection() : doc.selection; if(!sel || sel.rangeCount === 0) return; var rng = (sel.rangeCount > 0) ? sel.getRangeAt(0) : sel.createRange(); //selectionとrangeを記録 set_range = rng; set_sel = sel; }
マウスやキーボードの操作があれば、フォーカスを戻す
とりあえずテキストフォームに入力したり、キーボード操作をしたら記憶したフォーカスが無いかを確認し、あればフォーカスを戻す処理を実行します。
$("body").on("mousedown keypress focus blur keyup", addEvent); function addEvent(){ if(set_sel === null && set_range === null) return; if(window.getSelection) { set_sel.removeAllRanges(); set_sel.addRange(set_range); } else { set_range.select(); } }
コマンド実行後などにフォーカスを削除する
処理を終えたらフォーカスしておく必要は無いので、変数を初期化します。
/* * リンクする */ $(document).on('click','#urllink',function(){ if( $("#link").val() ){ doc.execCommand('createlink', false, $("#link").val()); $("#link").val(''); } set_sel = null; set_range = null; });
なんて事をやれば、IEさんでもいけます。Widows10でIEはSpartanという名称に変わるそうですが、レンダリングエンジンは変わらないそうです・・・バージョンアップごとにWEB屋の頭を悩ませるブラウザですので、また何か変更が有りそうで怖いですね。
とりあえず自分用の予定ですが、WYSIWYGエディターを暇なときに作ってみようかと思います。