【Salesforce】Visualforceの画面表示時にフォーカスが当たる件について
Visualforceで作成した画面を表示する際、一番上にあるinput要素にフォーカスが当たります。
それだけならまだ良いのですが、日付や日付/時間の項目だったりするとカレンダーも表示されるんですよね。
これを解決する方法は色んな方が書かれているように
<script> beenFocused = true; </script>
とするだけで解決します。
なぜそれだけで解決するのか気になったため、追ってみました。
beenFocusedという変数は、main.jsで定義されているようです。
難読化されていますが、こんな感じです。
var beenFocused = !1, focusedElement = null, textAreaTimer = null;
javascriptで1はtrueですから、その否定で初期値はfalseが入っているのでしょうか。
つづいて、このような記述があります。
function markFocused() { beenFocused = !0 } addEvent(document, "mousedown", markFocused);
画面をカチっとした際に、beenFocusedをtrueにしているようです。
この部分を見ただけではあまり関係なさそうです。
beenFocusedを使っているメソッドに、こういうものがありました。
function setFocusOnLoad() { beenFocused || setFocus() }
beenFocusedとsetFocus()の戻り値で論理和を出していますが、値は返していないようです。
setFocusの中身はこんな感じです。
function setFocus() { for (var a = 1; 5 > a; a++) for (var b = a, c = 0; c < document.forms.length; c++) for (var d = document.forms, e = 0; e < d.elements.length; e++) { var f = d.elements[e]; if (f.tabIndex == b) { if (("text" == f.type || "textarea" == f.type || "password" == f.type) && !hiddenOrDisabledOrReadOnly(f) && "sbstr" != f.name && 0 != f.name.indexOf("owner") && 0 != f.name.indexOf("tsk1") && 0 != f.name.indexOf("evt1") && "tsid" !== f.name) return f.focus(), "text" == f.type && f.select(), !0; b++; e = 0 } } for (c = 0; c < document.forms.length; c++) if (d = document.forms, a = d.name, "sbsearch" != a && "srch_solution_sbar" != a && "srch_product_sbar" != a && "srch_document_sbar" != a && "srch_article_sbar" != a) for (e = 0; e < d.elements.length; e++) if (f = d.elements[e], "true" != f.getAttribute("data-skipFocus") && ("text" == f.type || "textarea" == f.type || "password" == f.type) && !hiddenOrDisabledOrReadOnly(f) && 0 != f.name.indexOf("owner") && "tsid" !== f.name) return f.focus(), "text" == f.type && f.select(), !0; return !0 }
まさに、フォーカスを当てている部分ですね。
完全に読み解くのは面倒ですが、何となくフォーム内にある要素にフォーカスを当てている雰囲気です。
setFocusOnLoad()を呼んでいるのは、Visualforceページに自動で定義されているbodyOnLoad()です。
function bodyOnLoad(){ setFocusOnLoad(); /* 長いので省略 */ }
bodyOnLoadメソッドはbodyタグのonload処理で呼ばれているようなので、画面を読み込んだ際に動きます。
実際にbeenFocusedを使用しているのはsetFocusOnLoad()のみなのですが、一見するとbeenFocusedの値に関わらずsetFocus()が動いているように見えます。
function setFocusOnLoad() { beenFocused || setFocus() }
しかし、論理和を出すだけに見えたこのメソッドは実際に論理和を出すためにこうなっているわけではないようです。
論理和はtrueであることが確定した時点で、その後の処理を行わずに値を返すようです。
たとえば
true || alert('test')
としていても、アラートは表示されません。
アラートの表示をする前にtrueを返すわけですね。
同じように、setFocusOnLoad()でも、beenFocusedがtrueの場合にはsetFocus()が呼ばれないわけです。
やっと謎の論理和の意味が分かりました。
こんな方法があるんですね。
そんなわけで、画面表示時にフォーカスを当てたくない場合に
<script> beenFocused = true; </script>
とする理由が分かりました。
ソースコードを読むのはいい勉強になります。
既に方法を示している皆さん、とっても勉強家だと思います。。
もし読んでいる方がいて、間違っている部分がありましたら教えてくださいませ。
No comments.