2016年01月23日の日記です


iOSでtextのコピー・ペーストができないバグの回避  2016-01-23 21:48:49  コンピュータ

iOSのJavascriptのバッドノウハウ。


iOS8でバグが報告され、iOS9になっても修正されなかった…つまりは「もはや仕様」のバグへの対処方法。


以前からお手伝いしている仕事で、ユーザーさんから指摘があってバグっていることを知った。

iOS8 からのバグだったのに、1年以上もデバッグ担当が誰も気づいていなかったという問題。


input TAG の type="text" か、textarea によってテキスト入力を作った際、テキスト部分の長押しで、全選択やコピー・ペーストなどのメニューが開く。


この際に、Javascript などが動作していて特定の処理を行っている場合、メニューが消えてしまい、結果的にコピー・ペーストなどの操作ができなくなる、というのがバグの概要だ。




特定の 処理とは、「画面全体の再レンダリングが必要となる処理」である。


画面の一部領域だけ書き換えれば済む問題はバグを引き起こさないようだ。

ここで「全体の再レンダリング」とは、スクロールのような処理を含まない。


スクロールは、単純に画面をコピーしてずらすだけだから。


より具体的にいえば、DOM 要素の style を変えることで、表示位置やサイズなどを変える。

より厳密にいえば、サイズを「変える」必要すらなく、「サイズに関与するプロパティ」に書き込みを行うだけでいい。


style 要素が変わればよい、という意味では、css の transition 指定や animation 指定でも同じことになる。

とにかく、テキストメニューが開いているときに、再レンダリングが起きること。


top left width height などの指定はもちろん、border padding margin などの指定でも起きる。


opacity などでは大丈夫な一方、box-shadow ではバグが起きた。

どうも、opacity はあらかじめ存在する矩形領域の中だけの「一部書き換え」で済むが、box-shadow は矩形領域の外側だというのが影響するようだ。



これらの変更が、HTML 内のどこかで使われているだけでバグが生じる。

テキストの近くにあるとか、画面表示領域内かどうかなどは無関係だ。




どうすればよいか。


お仕事のプログラムでは、テキスト入力のある画面内で、javascript でアニメーションしている部分があった。


このアニメーションは、setInterval で動いていた。

そこで、一定時間ごとに動作する関数の冒頭で、text 入力中かどうかを確認し、入力中なら何もせずに return することにした。


お仕事では、テキスト入力はダイアログを出して行うことにしていたので、ダイアログに相当する div が「表示されている」ことを確認して return していた。


document.activeElement を使うと、現在フォーカスしている DOM 要素を取得できる。

document.activeElement.id とすれば、その DOM 要素の id を知ることもできる。


これを使って、text 入力にフォーカスされていたら何もしない、とする方法ならどんな場合でも使えそうだ。


#僕は試していないので、うまくいかなかったら申し訳ない。




Javascript ならこの程度の対処で済むのだけど、問題は CSS で animation 指定などをしている時だ。

CSS なので、Javascript と違って「状況によって何もしない」というプログラムを作ることはできない。


そのアニメが本当に必要か考えて、不要なら失くしてしまうのも手だ。

今回は、大したアニメではなかったので、失くしてしまうことで解決した。



次善の策は、text 入力に focus / blur イベントを仕掛けて置いて、animation する DOM の class を変えてやる方法だろう。

そして、この class が付いた場合のみ、animation するように css を作っておく。


jQuery があればこんな感じかな。


#こちらも試してない


▼javascript

$('input[type="text"]').bind("focus",function(){
  $(".anim").removeClass("move");
}).bind("blur",function(){
  $(".anim").addClass("move");
});

▼css

.anim.move {
  animation:~
}


上のコードは、input type="text" にフォーカスが当たったら、class="anim move" のタグから、move を取り去る。

そして、フォーカスが消えたら、class="anim" のタグに move を加える。


css では、class="anim move" のタグに対してアニメの指定をしている。

text にフォーカスした時は、 move が消えるのでアニメは止まる。




同じテーマの日記(最近の一覧)

コンピュータ

別年同日の日記

12年 ゲームボーイの CPU

15年 アプリケーションサーバとしてのQNAP

15年 宮永好道 命日(1993)

18年 サターンポリゴンのゆがみ

21年 100倍規模


申し訳ありませんが、現在意見投稿をできない状態にしています


戻る
トップページへ

-- share --

0000

-- follow --




- Reverse Link -