Upgrade to Pro — share decks privately, control downloads, hide ads and more …

What We Talk About When We Talk About Editor

What We Talk About When We Talk About Editor

ブラウザ内のエディタ事情

Masafumi Oyamada

August 18, 2012
Tweet

More Decks by Masafumi Oyamada

Other Decks in Programming

Transcript

  1. id:mooz / @stillpedant ┃アドオン開発  KeySnail: Firefox を Emacs ライクに

     Clipple: クリップボード拡張  gpum: Gmail 用のポップアップ・インタフェース ┃Firefox Hacks Rebooted  KeySnail について  ECMAScript5 について ┃See also  http://mooz.github.com/index-ja.html 2
  2. <textarea> ┃最も馴染み深いブラウザ内エディタ: <textarea>  ブログの更新  Web メーラー ┃編集機能は貧弱 

    基本的なカーソルの移動操作  カット,ペースト,アンドゥ ┃高度な編集機能が欲しい  文字列の置換機能  スニペット機能  矩形編集機能 6 どうやって独自の編集機能を実現する?
  3. 独自の編集機能に必要なもの ┃基本的な操作  エディタ内のテキストを取得  カーソル位置の取得と設定  選択範囲の取得と設定  テキストの編集

     挿入: insert(start, text)  削除: delete(start, end) ┃高度な編集機能  上記の操作を組み合わせて実装可能 7 基本的な操作はどう実現する?
  4. テキストの取得 ┃テキストの取得  var textArea = document.querySelector(“#editor”);  var wholeText

    = textArea.value; ┃テキストの設定  textArea.value = “abc”;  注意点  テキストを設定するとテキストエリアのスクロール位置が先頭 へとリセットされる  設定前にスクロール位置 (scrollTop) を保存し,設定後にスク ロールし直す必要がある 8 var savedScrollTop = textArea.scrollTop; textArea.value = someText; textArea.scrollTop = savedScrollTop;
  5. テキストの編集: 単純な方法 ┃単純な方法  編集後のテキストを文字列操作で生成  生成したテキストを textArea.value に代入 11

    function insert(start, insertText) { var originalText = textArea.value; textArea.value = originalText.substring(0, start) + insertText + originalText.substring(start); } function delete(start, end) { var originalText = textArea.value; textArea.value = originalText.substring(0, start) + insertText + originalText.substring(0, end); } 手作業で 編集後の文字列を 計算してあげる 手作業で 編集後の文字列を 計算してあげる
  6. テキストの編集: 賢い方法 ┃賢い方法  textArea の TextNode を直接操作 ┃利点 

    まどろっこしい文字列操作がいらない  JS レベルでの操作が少ないため高速?(未検証) 12 function insert(start, text) { var textNode = textArea.firstChild; textNode.insertData(start, text); } function delete(start, end) { var textNode = textArea.firstChild; textNode.replaceData(start, end - start, „‟); } firstChild
  7. 高度な編集機能の実現 ┃基本的な操作がそろった  エディタ内のテキストを取得  カーソル位置の取得と設定  選択範囲の取得と設定  テキストの編集

    ┃基本的な操作を組み合わせて置換機能を実現  textArea.value.indexOf() などで置換対象文字列を検索  置換対象文字を選択してハイライト  delete(replacee), insert(replacer) して置換を実行  (textNode.replaceData を使えば一発) 13 基本的な操作さえあれば高度な機能が実現できる
  8. さまざまなブラウザ内エディタ ┃Ymacs  http://www.ymacs.org/ ┃CodeMirror 2  http://codemirror.net/  jsdo.it

    も利用 ┃ACE Editor  http://ace.ajax.org/ ┃Skywriter (Bespin) [Ace Editor へ移行]  https://mozillalabs.com/en-US/skywriter/ ┃Eclipse Orion  http://www.eclipse.org/orion/  Firefox の Scratch Pad も利用 17 構文の強調表示など <textarea> では実現できないことを 実現するために頑張っている
  9. 独自エディタの分類 ┃1. キーイベント全解釈タイプ  Ymacs ┃2. contentEditable タイプ  Eclipse

    Orion  CodeMirror 1  多くの WYSIWYG エディタ  Evernote, Gmail, Tumblr, … ┃3. hidden textarea タイプ  CodeMirror 2  ACE Editor 18 ブラウザの用意した 入力機構を使うタイプ 独自の入力機構を使うタイプ
  10. 1. キーイベント全解釈タイプ ┃方針  イベントリスナを使って全てのキーイベントを監視  イベントを順に解釈することでビューを構築 ┃例  入力イベント列:

    a, b, <backspace>, c, <left>, d  生成されるビュー: a d c 19 Ymacs カーソル Ymacs ユーザ イベントリスナ キー入力 入力が不可能なビュー (<div>,<span>, …) イベントを解釈し ビューを構築
  11. キーイベント全解釈タイプの利点・欠点 ┃利点  自由度高 ┃欠点  マルチバイト文字の入力が実現し難い  IME がからむとキーイベントがまともに飛ばない

     Ymacs もマルチバイト文字の入力は未サポート  コンテキストメニューからの編集ができない  ビューが入力可能要素ではない  キーイベントが飛ばない 20 Ymacs ユーザ イベントリスナ キー入力 入力が不可能なビュー (<div>,<span>, …) イベントを解釈し ビューを構築
  12. 2. contentEditable タイプ ┃方針  ビュー要素に contentEditable 属性を設定し入力可能に  ビューの構築は基本的にブラウザ任せ

     一部のキー入力のみを独自に解釈  ショートカットキーの実現 21 Eclipse Orion CodeMirror 1 ユーザ キー入力 contentEditable で入力可能なビュー (<div>,<span>, …)
  13. contentEditable タイプの利点・欠点 ┃利点  入力関係の問題が生じにくい(マルチバイト文字)  コンテキストメニューからの編集も問題ない ┃欠点  ブラウザにより

    contentEditable 系の挙動が異なる  差異を吸収するために多くのコードを書く必要がある  CodeMirror はこれにこりて 2 で contentEditable から脱却  エディタ要素を iframe 内に仕込む必要がある  初期化が同期的ではなく,これによる問題が多々発生 22 Eclipse Orion CodeMirror 1 ユーザ キー入力 contentEditable で入力可能なビュー (<div>,<span>, …)
  14. 3. hidden textarea タイプ ┃方針  hidden な textarea を用意してユーザの入力を受け付け

     textarea にフォーカスしておく  textarea の内容からビューを構築 23 CodeMirror2 ACE Editor Ymacs ユーザ hidden な textarea キー入力 入力が不可能なビュー (<div>,<span>, …) textarea の中身を見て ビューを構築
  15. hidden textarea タイプの利点・欠点 ┃利点  ブラウザ間の挙動の違いに悩まされなくて良い ┃欠点  実装が大変 

    http://codemirror.net/doc/internals.html  コンテキストメニューからの操作がほぼ効かない  「全選択」など 24 Ymacs ユーザ hidden な textarea キー入力 入力が不可能なビュー (<div>,<span>, …) textarea の中身を見て ビューを構築 CodeMirror2 ACE Editor
  16. source-editor.jsm ┃resource:///modules/source-editor.jsm  Firefox 11 より(公式に)利用可能に  アドオン内でソースコードエディタを実現 ┃様々なバックエンド 

    SourceEditor は単なるエディタインタフェース  ビューを含む実際の挙動はバックエンド次第  デフォルトのバックエンド: Eclipse Orion  contentEditable タイプ 27 SourceEditor Orion アドオン YYY ZZZ
  17. source-editor.jsm の使い方 ┃エディタの挿入場所の用意 (placeholder) ┃SourceEditor の初期化 28 <vbox id="editor" flex="1"/>

    var placeholder = document.getElementById("editor"); var config = { mode: SourceEditor.MODES.JAVASCRIPT, showLineNumbers: true }; var editor = new SourceEditor(); editor.init(placeholder, config, function onInitialize() { // 初期化後の処理 });
  18. 何が嬉しいか ┃SourceEditor に対する高度な編集機能  SourceEditor の用意する基本操作を組み合わせて実現  いちど実装してしまえば様々なバックエンドで動作  エディタに対する統一的なインタフェース

    ┃SourceEditor の利用により  もう↓のようなことにならなくて済む 29 ┃高度な編集機能の実現  エディタ実装毎にコードを書く必要がある  大変  きりがない
  19. まとめ 31 ┃<textarea> における高度な編集機能  基本的な操作さえあれば実装できる ┃ 独自エディタ  三種類の実装方式がある

     高度な編集機能は実装毎に書く必要があり大変 ┃source-editor.jsm  Firefox 11 より利用可能  ソースコードエディタに対する統一的なインタフェース