テキスト編集を強力にサポートするブックマークレット作り

前回、カーソル移動キーのないiPadのソフトウェアキーボードを補うために、文字カーソルを左右に移動するブックマークレットを作ってみた。実際に試してみると、自分の中では好感触!悪くない。

しかし、現状はシンプルすぎる(いや、一般性のない限定的な条件でしか使えない)スクリプトなので、使い勝手がすこぶる悪い...。はてなダイアリー本文(タイトルは駄目)の編集でしかカーソル移動できないのだ。あり得ん。

javascript:
var el = document.getElementById('textarea-edit');
el.setSelectionRange(el.selectionStart-1, el.selectionStart-1);

カーソル移動

欲しいのは、id属性に依存しない、編集中のテキストなら何処でもカーソル移動できるボタンなのだ。そこで...

  • フォーカスの当たっているエレメントを取得して、操作するように変更してみた。
  • テキストが範囲選択されている場合は、範囲の始点または終点に移動する。(現実のキーボードと同じ仕様)
戻る
javascript:
var fn = document.getSelection().focusNode;
var el = fn.getElementsByTagName('textarea')[0] || fn.getElementsByTagName('input')[0];
if(el.selectionStart == el.selectionEnd){
el.setSelectionRange(el.selectionStart-1, el.selectionStart-1);
}else{
el.setSelectionRange(el.selectionStart, el.selectionStart);
}
進む
javascript:
var fn = document.getSelection().focusNode;
var el = fn.getElementsByTagName('textarea')[0] || fn.getElementsByTagName('input')[0];
if(el.selectionStart == el.selectionEnd){
el.setSelectionRange(el.selectionEnd+1, el.selectionEnd+1);
}else{
el.setSelectionRange(el.selectionEnd, el.selectionEnd);
}

ブックマークレットの登録方法

  • 好みの名称で何処かのページをブックマークバーに一旦登録する。
  • 上記のブックマークを編集モードにして、必要なJavaScriptコードをURL欄にペーストする。
  • (注意)半角の\nが、半角の¥nになってしまっているので、以下のブックマークレットでは一旦メモ帳にペーストして、修正する必要あり。
    • 段落の先頭・末尾へジャンプ。
    • テキストエリアの自動リサイズ。

以上で完了。

カーソルジャンプ

また、テキスト入力中に先頭・末尾に移動したいこともよくある。そこで...

  • 改行コードを目印に、段落の先頭・末尾に移動するスクリプトを作ってみた。
  • 現実のキーボードショートカットcontrol-A・control-Eに相当する。
    • 但し、連続操作した時は、次の先頭・末尾を目指して、カーソルが上または下へ次々と移動する。
    • 上下の矢印キーがない環境では、この方が便利と思ったので。
段落の先頭へジャンプ
javascript:
var fn = document.getSelection().focusNode;
var el = fn.getElementsByTagName('textarea')[0] || fn.getElementsByTagName('input')[0];
el.setSelectionRange(el. selectionStart-1, el.selectionStart-1);
for(i=0;i<200;i++){
  el.setSelectionRange(el.selectionStart-1, el.selectionStart);
  var sel = document.getSelection();
  if(sel=="\n"){
    el.setSelectionRange(el.selectionStart+1, el.selectionStart+1);
    break;
  }
}
  • 以下、改良バージョン
javascript:
var fn = document.getSelection().focusNode;
var el = fn.getElementsByTagName('textarea')[0] || fn.getElementsByTagName('input')[0];
var str = el.value.substr(0, el.selectionStart-1);
var offset = str.split(/\n|\r/).pop().length+1;
el.setSelectionRange(el.selectionStart-offset, el.selectionStart-offset);
段落の末尾へジャンプ
javascript:
var fn = document.getSelection().focusNode;
var el = fn.getElementsByTagName('textarea')[0] || fn.getElementsByTagName('input')[0];
el.setSelectionRange(el.selectionEnd+1, el.selectionEnd+1);
for(i=0;i<200;i++){
  el.setSelectionRange(el.selectionEnd, el.selectionEnd+1);
  var sel = document.getSelection();
  if(sel=="\n"){
    el.setSelectionRange(el.selectionEnd-1, el.selectionEnd-1);
    break;
  }
}
  • 以下、改良バージョン
javascript:
var fn = document.getSelection().focusNode;
var el = fn.getElementsByTagName('textarea')[0] || fn.getElementsByTagName('input')[0];
var str = el.value.substr(el.selectionEnd+1);
var offset = str.split(/\n|\r/).shift().length+1;
el.setSelectionRange(el.selectionEnd+offset, el.selectionEnd+offset);

選択範囲

さらには、カーソル移動しながら範囲を選択したいこともしばしば。そこで...

  • 選択範囲の終点を操作して、拡大・縮小するスクリプトを作ってみた。
  • 現実のキーボードショートカットshift-←・shift-→に相当する。
範囲を縮小、あるいは戻る方向へ移動する
javascript:
var fn = document.getSelection().focusNode;
var el = fn.getElementsByTagName('textarea')[0] || fn.getElementsByTagName('input')[0];
el.setSelectionRange(el.selectionStart, el.selectionEnd-1);
範囲を拡大する
javascript:
var fn = document.getSelection().focusNode;
var el = fn.getElementsByTagName('textarea')[0] || fn.getElementsByTagName('input')[0];
el.setSelectionRange(el.selectionStart, el.selectionEnd+1);

テキストエリアを自動リサイズする

iPadでテキストエリア内をスクロールするには、2本指でフリックする。しかし、1本指のフリックの時と違って慣性がほとんどなく、滑らかさがない。長い範囲のスクロールではなかなか進まずイライラする。
そもそも、テキストエリアに十分な高さがあれば、テキストエリア内のスクロールは不要になり、すべては1本指で滑らかに操作できるのだ。
でも、テキストエリアの最適な高さって、一体どれくらいだろう?無駄に高過ぎるとやはり苦労するし、短過ぎるとまた2本指でイライラすることになる。そこで...

  • テキスト入力に応じて、テキストエリアの高さを自動的に調整するスクリプトを作ってみた。
  • 文字入力毎にテキストエリア内の改行を数えて、高さを調整している。(3行目)
    • 改行数+25の設定。this.value.split('\n').length+25。
  • 一段落が複数行になりがちなタイプなら、以下のように修正しても良さそう。
    • 改行数×2+1の設定。this.value.split('\n').length*2+1。
javascript:(function(){
  function _resize(){
    this.setAttribute('rows', this.value.split('\n').length+25);
  }
  var els = document.getElementsByTagName('textarea');
  for (i = 0; i < els.length; i++){
    els[i].style.height = 'auto';
    els[i].style.overflow = 'auto';
    els[i].addEventListener('input', _resize, false);
    els[i].addEventListener('focus', _resize, false);
  }
})();

ブックマークバーについて

以上のブックマークレットを前回までの環境に追加修正すると、iPadSafariは、このような状態となる。

  • ブックマークレットの名称は、最低でも日本語フォント3文字分の幅は欲しい。
    • 3文字未満(指の幅より狭い名称)だと、押し間違いが多くなる。
    • タッチした時の反応が顕著に悪くなる気がした。
  • また、小文字よりは大文字の方がタッチした時の反応が良い気がした。
  • カーソル操作のブックマークレットは、バー右側に寄せた方が操作しやすかった。
    • 中央付近では、文字カーソルの動きが手に隠れてしまい使いにくい。
    • 右手でのタッチ操作がメインなので、操作の移動が少ない右側に落ち着いたのだ。

課題と所感

  • ブックマークバーや戻る・進む・ページ選択等のコントロールの位置が、iPhoneSafariのように画面下部に配置された方が操作しやすいと思う。
  • しかし、iPadSafariでは、画面上部に配置される仕様。操作する時に手の移動距離が多くなってしまい、かったるい。
  • ブックマークレットを操作した時の明確なリアクションが欲しい。
  • タッチした時の音もなく、色の変化も分かりにくいので、正しくタッチできたかどうか不安が残る。
  • ソフトウェアキーボードのback deleteキーのような、押し続けた時のリピート機能も欲しい。
  • シフトキーを併用した状態を感知して、ブックマークレットを実行したい。
  • 以上の課題は、JavaScriptで対応できそうなこともあれば、iOS側の対応に期待するしかない部分もある。今後も、できることから地道に改良して、テキスト編集の操作性の向上を目指して行く予定。
  • 懲りずに、この日記もまたAll iPadでの投稿。JavaScriptの検索・コード書き・テスト等も含めてすべてをiPadで作業した。
  • まだまだ課題は多いが、ブックマークレットマルチタスク用ジェスチャで、iPadはかなり実用的なテキスト編集環境になってきた!