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

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

040e5cf6a6367b485e5a86e519011b28?s=128

stillpedant

August 18, 2012
Tweet

Transcript

  1. ブラウザ内のエディタ事情 1 id: mooz / @stillpedant

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

     Clipple: クリップボード拡張  gpum: Gmail 用のポップアップ・インタフェース ┃Firefox Hacks Rebooted  KeySnail について  ECMAScript5 について ┃See also  http://mooz.github.com/index-ja.html 2
  3. 発表の内訳 エディタ 80% 拡張機能 20% 3

  4. 発表の流れ 1. <textarea> における高度な編集機能  どのように高度な編集機能が実装されるかを解説 2. 独自エディタ  ブラウザ内エディタを分類しその実装を解説

    3. source-editor.jsm  Firefox 11 より利用可能となった source-editor.jsm に ついて概説 4
  5. 5 <textarea> における高度な編集機能

  6. <textarea> ┃最も馴染み深いブラウザ内エディタ: <textarea>  ブログの更新  Web メーラー ┃編集機能は貧弱 

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

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

    = textArea.value; ┃テキストの設定  textArea.value = “abc”;  注意点  テキストを設定するとテキストエリアのスクロール位置が先頭 へとリセットされる  設定前にスクロール位置 (scrollTop) を保存し,設定後にスク ロールし直す必要がある 8 var savedScrollTop = textArea.scrollTop; textArea.value = someText; textArea.scrollTop = savedScrollTop;
  9. カーソル位置の操作 ┃カーソル位置  テキストの先頭からみたカーソルのオフセット  改行文字もカウントされる ┃カーソル位置の取得 ┃カーソル位置の設定 9 function

    setCaret(textArea, caret) { textArea.setSelectionRange(caret, caret); } function getCaret(textArea) { return textArea.selectionStart; } abcd 3
  10. 選択範囲の取得と設定 ┃選択範囲の取得  textArea.selectionStart  textArea.selectionEnd ┃選択範囲の設定  textArea.setSelectionRange(start, end)

     HTML5 では setSelectionRange(start, end, “backward”) などとできる 10 forward backward
  11. テキストの編集: 単純な方法 ┃単純な方法  編集後のテキストを文字列操作で生成  生成したテキストを 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); } 手作業で 編集後の文字列を 計算してあげる 手作業で 編集後の文字列を 計算してあげる
  12. テキストの編集: 賢い方法 ┃賢い方法  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
  13. 高度な編集機能の実現 ┃基本的な操作がそろった  エディタ内のテキストを取得  カーソル位置の取得と設定  選択範囲の取得と設定  テキストの編集

    ┃基本的な操作を組み合わせて置換機能を実現  textArea.value.indexOf() などで置換対象文字列を検索  置換対象文字を選択してハイライト  delete(replacee), insert(replacer) して置換を実行  (textNode.replaceData を使えば一発) 13 基本的な操作さえあれば高度な機能が実現できる
  14. コーヒーブレイク ┃Emacs  http://www.gnu.org/software/emacs/ 14 http://cpplover.blogspot.jp/2012/08/vim-vs-emacs.html

  15. コーヒーブレイク ┃Ymacs  http://www.ymacs.org/  ブラウザ上に Emacs を再現 15

  16. 16 独自エディタ

  17. さまざまなブラウザ内エディタ ┃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> では実現できないことを 実現するために頑張っている
  18. 独自エディタの分類 ┃1. キーイベント全解釈タイプ  Ymacs ┃2. contentEditable タイプ  Eclipse

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

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

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

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

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

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

    http://codemirror.net/doc/internals.html  コンテキストメニューからの操作がほぼ効かない  「全選択」など 24 Ymacs ユーザ hidden な textarea キー入力 入力が不可能なビュー (<div>,<span>, …) textarea の中身を見て ビューを構築 CodeMirror2 ACE Editor
  25. さまざまなエディタ実装 ┃高度な編集機能の実現  エディタ実装毎にコードを書く必要がある  大変  きりがない ┃どうにかならないか 

    統一的なインタフェースがあると良い 25
  26. 26 source-editor.jsm

  27. source-editor.jsm ┃resource:///modules/source-editor.jsm  Firefox 11 より(公式に)利用可能に  アドオン内でソースコードエディタを実現 ┃様々なバックエンド 

    SourceEditor は単なるエディタインタフェース  ビューを含む実際の挙動はバックエンド次第  デフォルトのバックエンド: Eclipse Orion  contentEditable タイプ 27 SourceEditor Orion アドオン YYY ZZZ
  28. 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() { // 初期化後の処理 });
  29. 何が嬉しいか ┃SourceEditor に対する高度な編集機能  SourceEditor の用意する基本操作を組み合わせて実現  いちど実装してしまえば様々なバックエンドで動作  エディタに対する統一的なインタフェース

    ┃SourceEditor の利用により  もう↓のようなことにならなくて済む 29 ┃高度な編集機能の実現  エディタ実装毎にコードを書く必要がある  大変  きりがない
  30. 30 まとめ

  31. まとめ 31 ┃<textarea> における高度な編集機能  基本的な操作さえあれば実装できる ┃ 独自エディタ  三種類の実装方式がある

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