2016/02/22

おのれ・・・

・・・また HTMLとJavaScriptに呪われて一日浪費した(# -д-)


■ 具体的には
ifarmeオブジェクト内のみ更新(F5キー操作と同じSuperReload)したかっただけ。
しかし、HTML側からは そうした機能は提供されていない。

そもそも ifarmeタグ は 本来廃止される予定だったモノだ、因って 至極仕方のナイ話としか云いようもナイのだが、
ナゼか最新のHTML5では ひっそりとは云え現場に返り咲いているので、使う機会も増えるハズだ。
■ iframe内の操作は
FireFox系ならブラウザの対象フレーム内でマウスを右クリックのコンテキストメニュー [このフレーム]項目に収まっていて、
その中の [フレームの再読み込み] を 実行すれば、そのフレームの内容だけが更新(再描画)される。

それを、サイトの意匠としてレイアウトしたボタンやリンクで実行したい。
ただ それだけのハナシだと考えて貰うと判り易いだろう。
■ で、巷のTipsでは
JavaScript で location.reload(true); を使え と云うトコばかり。
確かに動いてくれれば別にソレで構わないのだが、コレが全く機能しない始末・・・

大前提として 対象のiframeオブジェクトに任意のIDを振り、getElementById を用いた
document.getElementById('Indexframe').contentWindow.location.reload(true);
▲ コレらでは、iframeオブジェクト内で呼び出している外部サイトを再描画させる事が出来ない。 この記述でも自分のサイトのある、自分のサーバ領域のページを表示させている場合は有効ではあるのも事実だが、 iframeを用いた演出の場合、別機材(サーバ)にある別ページを表示するケースが大多数だろう。 その場合にこの記述では全く役に立たなかった・・・ そして 多くのTipsサイトにも当然
仕様として iframeオブジェクト内に呼び出した "外部コンテンツ" には 更新系処理が作用しない。
このように注釈されている。 しかしナゼか 適切な対策は掲載されていない。 そうした中、.reloadの代替案の1つとして、JavaScriptで iframeオブジェクト内を消去/書き込みする処理を 関数化した少し凝ったモノがあり、その紹介ログのコメント投稿から 利用実績もあるようようだったの飛びついたのだが、 残念ながらその仕組みでも、その他の aタグや spanタグでの直接記述群と同様 全く動作しなかった・・・ 仕方が無いので、昨日半日使って 簡易な方法を模索した次第。
★ その結果・・・ ■ この用法で、成否を分ける差異は、恐らく この2点のみ。
× location.reload(); を用いて "更新" するのではなく、
<input id="pbRefresh00" type="button" value="更新" onclick="frames.Indexframe.location.reload();" />
◎ location.replace('URL'); で、再度 対象サイトを呼び出すカタチが、この用法では正解。
<input id="pbRefresh00" type="button" value="更新" onclick="frames.Indexframe.location.replace('URL');" />
コレを id ではなく、上記のように class で 実行すると、欲しい結果が得られた。・・・以下の説明通りの解釈なら、コレが最重要ポイントだ。
★ この項目では参考までに、そのままテンプレートとして使えるよう、ボタンオブジェクトに直接JavaScriptを列挙した。

因みに 云わずもかカモ知れないが、色付きの部分は 各位のサイトに合わせて任意に設定すべき項目で、Indexframe と
なっている部分が、サンプルHTMLに配置した 対象の iframeオブジェクトへ設定されている class名 である。
■ 察しの良い向きなら
この時点で もうお気付きだろうが・・・
この用法の場合、iframeオブジェクトに対して id を 割り当てても、iframe内更新用途で利用するコトは出来ないのだ(-_-;)
■ 厳密に云うと・・・
その前提として、id と class の違いを理解する必要がある。
と云っても、そんなに難しいハナシでもナイ。
・class は、ランタイムなどのライブラリから提供されている機能に名前をつけて複製し、機能させる。
・id は、複製された機能に、固有の識別文字列を付与するだけ。
・・・と理解すれば、一旦は判り易い。
上述の通り id は、クローンされた機能に憑けられた "名前ですらない固有キーな文字列" でしかない。 単なる識別用文字列である id を 用いてオブジェクトを呼び出すには、オブジェクト群に振られた 全てのIDを順に検索し、そのIDが付与されている対象を見つける必要がある。 その処理を担うのが、
getElementById('Indexframe')
 であると、雑ながら認識していいだろう。  idを持つオブジェクト群を検索し、指定のid文字列を持つ  オブジェクトを検出、それを呼び出すまでが その仕事だ。
そして 呼び出した対象に、更に続く文字列で
getElementById('idString').location.replace('URL');
 任意の操作を実行させる仕組みだ。
しかし、こうした間接的呼び出しに全権限を与えるのは極めて危険な行為である為、モノに寄っては機能が制限されている。 ・・・iframeオブジェクトでも そうした制約が、多くの機能で課されているようだ。 ツマり、getElementByIdで獲た iframeオブジェクトに対して、表示している中身を読み込み直す制御 .reload(true); や .replace('URL'); を実行したとしても、機能するのは、表示しているサイトが 配置されている物理サーバ内のコンテンツのみに限定され、LAN内の 他の所有マシンも含む "外部機器にあるサイト" からの、再読み込みに依る再描画(更新/SuperReload)は、サポートしていないのだ。
まぁ 悪意のあるコードを含む他者のサイトをガンガン表示されまくっても困るしね・・・(´ヘ`;)

それに get "Element" ById・・・ IDを元に "要素" を得る だから、
オブジェクトそのもの全てを獲得する処理ではナイのかも知れないね。
■ 対して そうした操作を、ローカルのHTMLや 当該のJavaScriptファイルへの直接記述であれば可能にしてくれるのは・・・
iframeオブジェクトへ割り当てた class名 を 用いた
frames.Indexframe.location.replace('URL');
 ・・・このようなスクリプトの記述である。
frames は Document内の iframeオブジェクトを束ねているモノで、 iframeオブジェクトのうち Class名を割り当ててあるモノなら、ドットに続いて直接列挙して呼び出せる。 識別固有文字列付与だけの idと異なり、classを指定すると云うのは、
クローンした機能に 実働可能な名前を付けている
 コトになる。
因って 直接プログラムに記述して呼び出すコトが可能で、機能を利用するのに概ね制限はナイ。
プログラムの外から呼び出せるかは、オブジェクトに定義されたセキュリティ設定に依存する。
対象が public宣言されていない限りは、外部からの直接呼出しは出来ないのが一般的で
且つ、HTML上でpublic宣言しても 適宜制限されて有効に作用しなかったハズ・・・
■ これらを踏まえると、
iframeオブジェクトの枠内を "再描画させる前提" であるなら、
他のオブジェクトで用いていないユニークな文字列を その class名として、適宜割り当てておくコト
が 準備として 必須となるのが判るだろう。
◆ 実際に作成したHTMLの大枠はコンなカンジ。 ・・・視認性優先で、JavaScriptの関数部分も併記している。
■ SampleHTML・・・ レイアウトを決める要素は全て削除して要点のみにしてある、各位のサイトデザインに合わせて引用して欲しい。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd"> <html lang="ja" xml:lang="ja" xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <meta http-equiv="Content-Language" content="ja" lang="ja" xml:lang="ja" /> <style type="text/css"> <!-- --> </style> <script language="javascript" type="text/javascript"> <!-- var objIndexframe; function ListRefresh() { objIndexframe = frames.Indexframe; objIndexframe.location.replace('任意のURL b'); return false; } // --> </script> <title>Sample</title> </head> <body> <iframe name="RemoteControler" class="Controlframe" frameborder="0" src="任意のURL a"> <p>Your browser does not support iframes.</p> </iframe> <iframe name="FileList" class="Indexframe" frameborder="0" src="任意のURL b"> <p>Your browser does not support iframes.</p> </iframe> <input id="pbRefresh00" type="button" value="更新" onclick="ListRefresh();" /> <input id="pbRefresh01" type="button" value="更新" onclick="frames.Indexframe.location.replace('任意のURL b');" /> </body> </html>
※ このサンプルは見た目上、Tabを半角スペース4文字に置換してある、そのままでも機能するが 任意に再置換して利用するのもアリだろう。 尚、この例での 描画更新処理対象となる iframeオブジェクトは Indexframe で、 ボタン pbRefresh01 が 直接JavaScriptを記述、pbRefresh00 が 関数化した ListRefresh() を呼び出す書式となる。
注) 上述の通り、コレは デザインに関わる要素が全て排除されたサンプルで、このまま実行してもマトモな表示はされない。    だが このサンプルは、適切に divなどの要素を配置し CSSを定義した状態で利用しているモノからの抜粋である。

0 件のコメント:

コメントを投稿