\r\n\t\t\t\r\n\t\t\r\n\t\r\n\t\r\n```\r\n\r\n下記、動作しないケース(先のエラーが発生する)\r\n**これを何かしらの方法で動作するようにしたい。**\r\n\r\n```html\r\n\t\r\n\t\r\n\t\r\n\t\r\n\tdocument write by external domain script\r\n\t\r\n\t\r\n\t\t
\r\n\t\t\t

document write by external domain script

\r\n\t\t\t

sample text. sample text. sample text. sample text. sample text. sample text.

\r\n\t\t\t
\r\n\t\t\t\there is target.\r\n\t\t\t
\r\n\t\t
\r\n\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n```\r\n\r\nよろしくお願い致します。","answerCount":2,"upvoteCount":0,"datePublished":"2015-11-04T09:50:47.221Z","dateModified":"2015-11-04T10:14:00.170Z","acceptedAnswer":{"@type":"Answer","text":"```javascript\r\n$(function() {\r\n getWritten(\"script.js\", function(html){\r\n $('#target').after(html);\r\n });\r\n});\r\n/**\r\n * ファイル名を与えた JS ファイル内で document.write() された文字列を取得して、コールバック関数に渡す。\r\n * @param {string} fileName *.js ファイル名\r\n * @param {Function} callback コールバック関数。第一引数に結果を受け取る。\r\n */\r\nfunction getWritten(fileName, callback) {\r\n var $iframe = $(\"
質問するログイン新規登録

Q&A

解決済

2回答

19032閲覧

外部ドメイン上のスクリプトのdocument.write処理の代替案について。

ikki57

総合スコア290

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

0グッド

0クリップ

投稿2015/11/04 09:50

編集2015/11/04 10:14

0

0

したいこと

  • 外部ドメイン上に、document.writeでhtmlタグを記述しているスクリプトがある。(これは前提となります
  • 上記を呼び出して、document.writeを実行し、タグ文字列を取得する。(それを任意の場所にappedする等、加工する)
  • ただし、同期的に読み込むのではなく、非同期に読み込む必要がある。(これは前提となります

非同期に読み込んだ場合、下記エラーが発生する。

Failed to execute 'write' on 'Document': It isn't possible to write into a document from an asynchronously-loaded external script unless it is explicitly opened.

http://so-zou.jp/web-app/tech/programming/javascript/dom/node/document/
に記載がある通り、

非同期で読み込まれる外部スクリプトからは、document.write()を実行できません。

上記をどうにかしたい。

サンプルコード

外部js

js

1 document.writeln("<div id='additional'>here is additional dom</div>");
html

下記、動作するケース

html

1 <!DOCTYPE html> 2 <html lang="ja"> 3 <head> 4 <meta charaset="UTF-8"> 5 <title>document write by external domain script</title> 6 </head> 7 <body> 8 <div class="wrapper"> 9 <h1>document write by external domain script</h1> 10 <p>sample text. sample text. sample text. sample text. sample text. sample text.</p> 11 <div id="target"> 12 here is target. 13 <!-- これは動く --> 14 <script src="http://example.com/js/script.js"></script> 15 </div> 16 </div> 17 </body> 18 </html>

下記、動作しないケース(先のエラーが発生する)
これを何かしらの方法で動作するようにしたい。

html

1 <!DOCTYPE html> 2 <html lang="ja"> 3 <head> 4 <meta charaset="UTF-8"> 5 <title>document write by external domain script</title> 6 </head> 7 <body> 8 <div class="wrapper"> 9 <h1>document write by external domain script</h1> 10 <p>sample text. sample text. sample text. sample text. sample text. sample text.</p> 11 <div id="target"> 12 here is target. 13 </div> 14 </div> 15 16 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script> 17 <script> 18 // # これはエラーになる 19 $(function() { 20 $('#target').after( 21 $("<script>").attr({src: "http://example.com/js/script.js"}) 22 ); 23 }); 24 </script> 25 </body> 26 </html>

よろしくお願い致します。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tozjp

2015/11/04 09:53

外部ソースを document.write ではない方法で書く事はできないという前提ですか?
ikki57

2015/11/04 09:55 編集

tozjpさん ご連絡ありがとうござます。 > 外部ソースを document.write ではない方法で書く事はできないという前提ですか? はい。 **document.writeで記述されている外部ソースがある**、ということが前提となります。
tozjp

2015/11/04 09:57

では、求めている挙動は何でしょうか。 とりあえず汎用性があるように、外部リソースが write している文字列を値として取得できればどうとでもなりますかね。
ikki57

2015/11/04 10:09 編集

そうですね、取得できれば何とかなるかと。 (サンプルコードのエラーでは、取得すらできない状態なので、まずは取得する、が第一になります) 詳細を申しますと、サンプルコードにあるように、 外部リソースが write している文字列(htmlタグ)を取得し、 そのhtmlタグを任意のDOMの後に連結したい(after)、が実装したいことになります。
guest

回答2

0

ベストアンサー

javascript

1$(function() { 2 getWritten("script.js", function(html){ 3 $('#target').after(html); 4 }); 5}); 6/** 7 * ファイル名を与えた JS ファイル内で document.write() された文字列を取得して、コールバック関数に渡す。 8 * @param {string} fileName *.js ファイル名 9 * @param {Function} callback コールバック関数。第一引数に結果を受け取る。 10 */ 11function getWritten(fileName, callback) { 12 var $iframe = $("<iframe hidden\/>"); 13 // iframe が DOM 上に存在しないとうまくいかないので一時的に出力する 14 $iframe.appendTo("body"); 15 var frameDocument = $iframe[0].contentWindow.document; 16 var scriptTag = "<script src=\"" + fileName + "\"><\/script>"; 17 frameDocument.open(); 18 // frame 内での window.setResult に結果受信用関数を作成する 19 $iframe[0].contentWindow.setResult = function(html) { 20 // 親フレーム上から用済みの iframe を除去する 21 $iframe.remove(); 22 // 取得した文字列には scriptTag が含まれているので削除してコールバックに渡す 23 callback(html.replace(scriptTag, "")); 24 }; 25 frameDocument.write( 26 "<div id=\"area-to-write\">" + 27 // div タグ内に scriptTag を貼る 28 scriptTag + 29 "<\/div>" + 30 "<script>" + 31 // div タグ内に出力された文字列を setResult() に渡す 32 "setResult(document.querySelector(\"#area-to-write\").innerHTML);" + 33 "<\/script>" 34 ); 35 frameDocument.close(); 36}

iframe で同期的に読み込んで親フレームのコールバック関数を呼びます。
あらゆる場面でしっかり正常に動作するかはわかりませんが、足がかり程度にはなると思います。

特に外部ソースが document.write 以外の DOM 操作をしているとどうなるかわかりません。
また、グローバル変数は勝手に親フレームと共有されませんので使いたい値があるなら渡さなければいけません。

引数 fileName をエスケープしていないので必要そうなら書き換えてください。

投稿2015/11/05 00:48

tozjp

総合スコア790

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ikki57

2015/11/11 07:13

tozjpさん 返信遅くなって申し訳ありません。 上記の件、現在確認中ですので、また追ってご連絡致します。 とりいそぎ回答頂きましてありがとうございます。
ikki57

2015/11/19 03:39 編集

返信遅くなり申し訳ありません。 頂いたコードにて要件を満たすことができ、また、ロジックの確認もできました。 * iframeを生成、そのdoument内で対象の外部scriptをwriteし、実行させる ``` <div id="area-to-write"> <script src="http://example.com/js/script.js"></script> <div id="additional">here is additional dom!!!</div> </div> ``` * 求める対象のDOMがwriteされる * 中身を取得する ```` document.querySelector(\"#area-to-write\").innerHTML ``` * 下記が取得される ``` <script src="http://example.com/js/script.js"></script> <div id="additional">here is additional dom!!!</div> ``` * 対象のDOMを取り出すための関数を、ともにwriteしておき実行させる(`setResult()`) * iframeを削除 * scriptタグは削除する * callbackに渡し、callbackにて意図するDOMにappendする $('#target').after(html) iframeに関する理解が足りておらず、下記等を参考に頂いたコードを理解することができました。 返信遅くなり、申し訳ありませんでした。 参考) ▼IFRAME の内容を動的生成する正しい方法 http://webos-goodies.jp/archives/51014876.html ▼ドキュメントに HTML 文字列を出力する, フレーム内にコンテンツを作成する(write() メソッドを使用) http://hakuhin.jp/js/iframe.html この度は誠にありがとうございました。 今後ともどうぞよろしくお願い致します。
tozjp

2015/11/19 12:18

ここまで真剣に意図を汲んで頂けるとは! 内容の方も何も補足すべきこともなく完璧なご理解だと思います。 ご解決もできたようで、回答して良かったと思います。
guest

0

javascript

1document.writeln = function(str){ 2 $('#target').after(str); 3}

というのはどうでしょうか。
影響を確認しながら使わなければいけませんが、今どきdocument.writelnなんて他で使わないんじゃないかと。もし心配なら、

javascript

1var docWrite = document.writeln; 2//↑退避しておいて 3document.writeln = function(str){ 4 $('#target').after(str); 5} 6//いろいろ処理して 7//↓後で戻す 8document.writeln = docWrite;

なんて書き方とかどうでしょう?

投稿2015/11/11 08:15

Lhankor_Mhy

総合スコア37634

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.29%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問