Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

id:mooz / @stillpedant ┃アドオン開発  KeySnail: Firefox を Emacs ライクに  Clipple: クリップボード拡張  gpum: Gmail 用のポップアップ・インタフェース ┃Firefox Hacks Rebooted  KeySnail について  ECMAScript5 について ┃See also  http://mooz.github.com/index-ja.html 2

Slide 3

Slide 3 text

発表の内訳 エディタ 80% 拡張機能 20% 3

Slide 4

Slide 4 text

発表の流れ 1. における高度な編集機能  どのように高度な編集機能が実装されるかを解説 2. 独自エディタ  ブラウザ内エディタを分類しその実装を解説 3. source-editor.jsm  Firefox 11 より利用可能となった source-editor.jsm に ついて概説 4

Slide 5

Slide 5 text

5 における高度な編集機能

Slide 6

Slide 6 text

┃最も馴染み深いブラウザ内エディタ:  ブログの更新  Web メーラー ┃編集機能は貧弱  基本的なカーソルの移動操作  カット,ペースト,アンドゥ ┃高度な編集機能が欲しい  文字列の置換機能  スニペット機能  矩形編集機能 6 どうやって独自の編集機能を実現する?

Slide 7

Slide 7 text

独自の編集機能に必要なもの ┃基本的な操作  エディタ内のテキストを取得  カーソル位置の取得と設定  選択範囲の取得と設定  テキストの編集  挿入: insert(start, text)  削除: delete(start, end) ┃高度な編集機能  上記の操作を組み合わせて実装可能 7 基本的な操作はどう実現する?

Slide 8

Slide 8 text

テキストの取得 ┃テキストの取得  var textArea = document.querySelector(“#editor”);  var wholeText = textArea.value; ┃テキストの設定  textArea.value = “abc”;  注意点  テキストを設定するとテキストエリアのスクロール位置が先頭 へとリセットされる  設定前にスクロール位置 (scrollTop) を保存し,設定後にスク ロールし直す必要がある 8 var savedScrollTop = textArea.scrollTop; textArea.value = someText; textArea.scrollTop = savedScrollTop;

Slide 9

Slide 9 text

カーソル位置の操作 ┃カーソル位置  テキストの先頭からみたカーソルのオフセット  改行文字もカウントされる ┃カーソル位置の取得 ┃カーソル位置の設定 9 function setCaret(textArea, caret) { textArea.setSelectionRange(caret, caret); } function getCaret(textArea) { return textArea.selectionStart; } abcd 3

Slide 10

Slide 10 text

選択範囲の取得と設定 ┃選択範囲の取得  textArea.selectionStart  textArea.selectionEnd ┃選択範囲の設定  textArea.setSelectionRange(start, end)  HTML5 では setSelectionRange(start, end, “backward”) などとできる 10 forward backward

Slide 11

Slide 11 text

テキストの編集: 単純な方法 ┃単純な方法  編集後のテキストを文字列操作で生成  生成したテキストを 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); } 手作業で 編集後の文字列を 計算してあげる 手作業で 編集後の文字列を 計算してあげる

Slide 12

Slide 12 text

テキストの編集: 賢い方法 ┃賢い方法  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

Slide 13

Slide 13 text

高度な編集機能の実現 ┃基本的な操作がそろった  エディタ内のテキストを取得  カーソル位置の取得と設定  選択範囲の取得と設定  テキストの編集 ┃基本的な操作を組み合わせて置換機能を実現  textArea.value.indexOf() などで置換対象文字列を検索  置換対象文字を選択してハイライト  delete(replacee), insert(replacer) して置換を実行  (textNode.replaceData を使えば一発) 13 基本的な操作さえあれば高度な機能が実現できる

Slide 14

Slide 14 text

コーヒーブレイク ┃Emacs  http://www.gnu.org/software/emacs/ 14 http://cpplover.blogspot.jp/2012/08/vim-vs-emacs.html

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

16 独自エディタ

Slide 17

Slide 17 text

さまざまなブラウザ内エディタ ┃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 構文の強調表示など では実現できないことを 実現するために頑張っている

Slide 18

Slide 18 text

独自エディタの分類 ┃1. キーイベント全解釈タイプ  Ymacs ┃2. contentEditable タイプ  Eclipse Orion  CodeMirror 1  多くの WYSIWYG エディタ  Evernote, Gmail, Tumblr, … ┃3. hidden textarea タイプ  CodeMirror 2  ACE Editor 18 ブラウザの用意した 入力機構を使うタイプ 独自の入力機構を使うタイプ

Slide 19

Slide 19 text

1. キーイベント全解釈タイプ ┃方針  イベントリスナを使って全てのキーイベントを監視  イベントを順に解釈することでビューを構築 ┃例  入力イベント列: a, b, , c, , d  生成されるビュー: a d c 19 Ymacs カーソル Ymacs ユーザ イベントリスナ キー入力 入力が不可能なビュー (
,, …) イベントを解釈し ビューを構築

Slide 20

Slide 20 text

キーイベント全解釈タイプの利点・欠点 ┃利点  自由度高 ┃欠点  マルチバイト文字の入力が実現し難い  IME がからむとキーイベントがまともに飛ばない  Ymacs もマルチバイト文字の入力は未サポート  コンテキストメニューからの編集ができない  ビューが入力可能要素ではない  キーイベントが飛ばない 20 Ymacs ユーザ イベントリスナ キー入力 入力が不可能なビュー (
,, …) イベントを解釈し ビューを構築

Slide 21

Slide 21 text

2. contentEditable タイプ ┃方針  ビュー要素に contentEditable 属性を設定し入力可能に  ビューの構築は基本的にブラウザ任せ  一部のキー入力のみを独自に解釈  ショートカットキーの実現 21 Eclipse Orion CodeMirror 1 ユーザ キー入力 contentEditable で入力可能なビュー (
,, …)

Slide 22

Slide 22 text

contentEditable タイプの利点・欠点 ┃利点  入力関係の問題が生じにくい(マルチバイト文字)  コンテキストメニューからの編集も問題ない ┃欠点  ブラウザにより contentEditable 系の挙動が異なる  差異を吸収するために多くのコードを書く必要がある  CodeMirror はこれにこりて 2 で contentEditable から脱却  エディタ要素を iframe 内に仕込む必要がある  初期化が同期的ではなく,これによる問題が多々発生 22 Eclipse Orion CodeMirror 1 ユーザ キー入力 contentEditable で入力可能なビュー (
,, …)

Slide 23

Slide 23 text

3. hidden textarea タイプ ┃方針  hidden な textarea を用意してユーザの入力を受け付け  textarea にフォーカスしておく  textarea の内容からビューを構築 23 CodeMirror2 ACE Editor Ymacs ユーザ hidden な textarea キー入力 入力が不可能なビュー (
,, …) textarea の中身を見て ビューを構築

Slide 24

Slide 24 text

hidden textarea タイプの利点・欠点 ┃利点  ブラウザ間の挙動の違いに悩まされなくて良い ┃欠点  実装が大変  http://codemirror.net/doc/internals.html  コンテキストメニューからの操作がほぼ効かない  「全選択」など 24 Ymacs ユーザ hidden な textarea キー入力 入力が不可能なビュー (
,, …) textarea の中身を見て ビューを構築 CodeMirror2 ACE Editor

Slide 25

Slide 25 text

さまざまなエディタ実装 ┃高度な編集機能の実現  エディタ実装毎にコードを書く必要がある  大変  きりがない ┃どうにかならないか  統一的なインタフェースがあると良い 25

Slide 26

Slide 26 text

26 source-editor.jsm

Slide 27

Slide 27 text

source-editor.jsm ┃resource:///modules/source-editor.jsm  Firefox 11 より(公式に)利用可能に  アドオン内でソースコードエディタを実現 ┃様々なバックエンド  SourceEditor は単なるエディタインタフェース  ビューを含む実際の挙動はバックエンド次第  デフォルトのバックエンド: Eclipse Orion  contentEditable タイプ 27 SourceEditor Orion アドオン YYY ZZZ

Slide 28

Slide 28 text

source-editor.jsm の使い方 ┃エディタの挿入場所の用意 (placeholder) ┃SourceEditor の初期化 28 var placeholder = document.getElementById("editor"); var config = { mode: SourceEditor.MODES.JAVASCRIPT, showLineNumbers: true }; var editor = new SourceEditor(); editor.init(placeholder, config, function onInitialize() { // 初期化後の処理 });

Slide 29

Slide 29 text

何が嬉しいか ┃SourceEditor に対する高度な編集機能  SourceEditor の用意する基本操作を組み合わせて実現  いちど実装してしまえば様々なバックエンドで動作  エディタに対する統一的なインタフェース ┃SourceEditor の利用により  もう↓のようなことにならなくて済む 29 ┃高度な編集機能の実現  エディタ実装毎にコードを書く必要がある  大変  きりがない

Slide 30

Slide 30 text

30 まとめ

Slide 31

Slide 31 text

まとめ 31 ┃ における高度な編集機能  基本的な操作さえあれば実装できる ┃ 独自エディタ  三種類の実装方式がある  高度な編集機能は実装毎に書く必要があり大変 ┃source-editor.jsm  Firefox 11 より利用可能  ソースコードエディタに対する統一的なインタフェース