Share
Embed
Transcript
31 slides
-
id:mooz / @stillpedant ┃アドオン開発 KeySnail: Firefox を Emacs ライクに
Clipple: クリップボード拡張 gpum: Gmail 用のポップアップ・インタフェース ┃Firefox Hacks Rebooted KeySnail について ECMAScript5 について ┃See also http://mooz.github.com/index-ja.html 2 -
発表の流れ 1. <textarea> における高度な編集機能 どのように高度な編集機能が実装されるかを解説 2. 独自エディタ ブラウザ内エディタを分類しその実装を解説
3. source-editor.jsm Firefox 11 より利用可能となった source-editor.jsm に ついて概説 4 -
<textarea> ┃最も馴染み深いブラウザ内エディタ: <textarea> ブログの更新 Web メーラー ┃編集機能は貧弱
基本的なカーソルの移動操作 カット,ペースト,アンドゥ ┃高度な編集機能が欲しい 文字列の置換機能 スニペット機能 矩形編集機能 6 どうやって独自の編集機能を実現する? -
独自の編集機能に必要なもの ┃基本的な操作 エディタ内のテキストを取得 カーソル位置の取得と設定 選択範囲の取得と設定 テキストの編集
挿入: insert(start, text) 削除: delete(start, end) ┃高度な編集機能 上記の操作を組み合わせて実装可能 7 基本的な操作はどう実現する? -
テキストの取得 ┃テキストの取得 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 function
setCaret(textArea, caret) { textArea.setSelectionRange(caret, caret); } function getCaret(textArea) { return textArea.selectionStart; } abcd 3 -
選択範囲の取得と設定 ┃選択範囲の取得 textArea.selectionStart textArea.selectionEnd ┃選択範囲の設定 textArea.setSelectionRange(start, end)
HTML5 では setSelectionRange(start, end, “backward”) などとできる 10 forward backward -
テキストの編集: 単純な方法 ┃単純な方法 編集後のテキストを文字列操作で生成 生成したテキストを 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); } 手作業で 編集後の文字列を 計算してあげる 手作業で 編集後の文字列を 計算してあげる -
テキストの編集: 賢い方法 ┃賢い方法 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 -
高度な編集機能の実現 ┃基本的な操作がそろった エディタ内のテキストを取得 カーソル位置の取得と設定 選択範囲の取得と設定 テキストの編集
┃基本的な操作を組み合わせて置換機能を実現 textArea.value.indexOf() などで置換対象文字列を検索 置換対象文字を選択してハイライト delete(replacee), insert(replacer) して置換を実行 (textNode.replaceData を使えば一発) 13 基本的な操作さえあれば高度な機能が実現できる -
さまざまなブラウザ内エディタ ┃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> では実現できないことを 実現するために頑張っている -
独自エディタの分類 ┃1. キーイベント全解釈タイプ Ymacs ┃2. contentEditable タイプ Eclipse
Orion CodeMirror 1 多くの WYSIWYG エディタ Evernote, Gmail, Tumblr, … ┃3. hidden textarea タイプ CodeMirror 2 ACE Editor 18 ブラウザの用意した 入力機構を使うタイプ 独自の入力機構を使うタイプ -
1. キーイベント全解釈タイプ ┃方針 イベントリスナを使って全てのキーイベントを監視 イベントを順に解釈することでビューを構築 ┃例 入力イベント列:
a, b, <backspace>, c, <left>, d 生成されるビュー: a d c 19 Ymacs カーソル Ymacs ユーザ イベントリスナ キー入力 入力が不可能なビュー (<div>,<span>, …) イベントを解釈し ビューを構築 -
キーイベント全解釈タイプの利点・欠点 ┃利点 自由度高 ┃欠点 マルチバイト文字の入力が実現し難い IME がからむとキーイベントがまともに飛ばない
Ymacs もマルチバイト文字の入力は未サポート コンテキストメニューからの編集ができない ビューが入力可能要素ではない キーイベントが飛ばない 20 Ymacs ユーザ イベントリスナ キー入力 入力が不可能なビュー (<div>,<span>, …) イベントを解釈し ビューを構築 -
2. contentEditable タイプ ┃方針 ビュー要素に contentEditable 属性を設定し入力可能に ビューの構築は基本的にブラウザ任せ
一部のキー入力のみを独自に解釈 ショートカットキーの実現 21 Eclipse Orion CodeMirror 1 ユーザ キー入力 contentEditable で入力可能なビュー (<div>,<span>, …) -
contentEditable タイプの利点・欠点 ┃利点 入力関係の問題が生じにくい(マルチバイト文字) コンテキストメニューからの編集も問題ない ┃欠点 ブラウザにより
contentEditable 系の挙動が異なる 差異を吸収するために多くのコードを書く必要がある CodeMirror はこれにこりて 2 で contentEditable から脱却 エディタ要素を iframe 内に仕込む必要がある 初期化が同期的ではなく,これによる問題が多々発生 22 Eclipse Orion CodeMirror 1 ユーザ キー入力 contentEditable で入力可能なビュー (<div>,<span>, …) -
3. hidden textarea タイプ ┃方針 hidden な textarea を用意してユーザの入力を受け付け
textarea にフォーカスしておく textarea の内容からビューを構築 23 CodeMirror2 ACE Editor Ymacs ユーザ hidden な textarea キー入力 入力が不可能なビュー (<div>,<span>, …) textarea の中身を見て ビューを構築 -
hidden textarea タイプの利点・欠点 ┃利点 ブラウザ間の挙動の違いに悩まされなくて良い ┃欠点 実装が大変
http://codemirror.net/doc/internals.html コンテキストメニューからの操作がほぼ効かない 「全選択」など 24 Ymacs ユーザ hidden な textarea キー入力 入力が不可能なビュー (<div>,<span>, …) textarea の中身を見て ビューを構築 CodeMirror2 ACE Editor -
さまざまなエディタ実装 ┃高度な編集機能の実現 エディタ実装毎にコードを書く必要がある 大変 きりがない ┃どうにかならないか
統一的なインタフェースがあると良い 25 -
source-editor.jsm ┃resource:///modules/source-editor.jsm Firefox 11 より(公式に)利用可能に アドオン内でソースコードエディタを実現 ┃様々なバックエンド
SourceEditor は単なるエディタインタフェース ビューを含む実際の挙動はバックエンド次第 デフォルトのバックエンド: Eclipse Orion contentEditable タイプ 27 SourceEditor Orion アドオン YYY ZZZ -
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() { // 初期化後の処理 }); -
何が嬉しいか ┃SourceEditor に対する高度な編集機能 SourceEditor の用意する基本操作を組み合わせて実現 いちど実装してしまえば様々なバックエンドで動作 エディタに対する統一的なインタフェース
┃SourceEditor の利用により もう↓のようなことにならなくて済む 29 ┃高度な編集機能の実現 エディタ実装毎にコードを書く必要がある 大変 きりがない -
まとめ 31 ┃<textarea> における高度な編集機能 基本的な操作さえあれば実装できる ┃ 独自エディタ 三種類の実装方式がある
高度な編集機能は実装毎に書く必要があり大変 ┃source-editor.jsm Firefox 11 より利用可能 ソースコードエディタに対する統一的なインタフェース