質問をすることでしか得られない、回答やアドバイスがある。

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

ただいまの
回答率

87.61%

GASで親ページのインフレームからリンクした子ページが表示されない。

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 3,161

score 17

前提・実現したいこと

質問に対しテラテイルから編集してはと連絡があり簡潔に編集しました。

ローカルで使用していた備忘録をGASに移植しました。
全体の構成
一つの親ページとメニューで選択される複数の子ページがあります。
親ページにはページの表題とBGMのコントローラとインフレームがあります。
子ページにはコンテンツの選択メニューとコンテンツがセットで複数あります。
インフレームには複数ある子ページをメニューで選択して表示します。

発生している問題・エラーメッセージ

問題点(➀と➁は以後共通)
 ➀親ページを表示するとインフレームに指定された子ページを表示します。
 (ここまで問題がありましたがテラテイルの力を借りて解決しました)
ここからが今回の問題点です。
 ➁メニューを選択すると選択した子ページをインフレームに表示します。
しかし➀はOKですが➁はNGです。
➁はインフレームが真白になってgoogleのエラー表示もありません。
デベロッパーのコンソールでエラーを見ると
 Uncaught TypeError: Cannot read property 'children' of undefined
     at HTMLDocument.changeFontSize (script.js:37)
で、実際GASのエディターで見ても同じエラーが出ていました。
リンク方法は
子ページへのリンクは➀と➁の2つありますが現在どちらも同じにしています、
 ➀<body onloadで呼ばれる関数のdocument.getElementById('ifrmencont').src = URLで
   親ページの<iframe src=""にURLを設定しています。
 ➁メニュー選択で呼ばれる関数のwindow.frameElement.src = URLで
   親ページの<iframe src=""にURLを設定しています。
結果的に全く同じですがなぜか動作が違います。```  

```

該当のソースコード

```ここに言語を入力

-----親ページのソースコード(index)
<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <?!= HtmlService.createHtmlOutputFromFile('Css').getContent(); ?> <!-- css読込 -->
  </head>
  <audio id="audio"></audio>
  <script type="text/javascript">
              |
    BGMコントローラの操作で省略
              |
    //子ページ読込
    function openURL(url) {
        var gglURL = "https://script.google.com/macros/s/AKfycbxQOayD1oYR8kFXeFRHSzlXMJSicQvQdEvVA0yJ_SiRydfPmr2B/exec?p="; //googleベースURL
        var praURL = gglURL + url; //ファイル名のパラメータ追加
        document.getElementById('ifrmencont').src = praURL; //iframeのsrcに設定
        //googleメッセージ消去テスト中
        var removeElem = document.getElementsByTagName("tr")[0]; //最初のtr要素取得(現在取得できない)
        alert(removeElem); //エラー確認用(現在undefined)
        removeElem.parentNode.removeChild(removeElem); //要素削除(現在取得できないのでエラー)
    }
  </script>
  <body onload="openURL('kousin')">
    <div id="hyobgmwak">
        <div id="hyowak">
            <div id="kamon">
                <img src="https://drive.google.com/uc?id=16GtqNtZEuxq6N_xi-f50brhIKySeAI1I" alt="〇〇〇家の家紋" width="55" height="55">
            </div>
            <div id="taitl">
                <h1>〇 〇 〇 家 の 備 忘 録</h1>
                <p>〇〇〇藤三郎の備忘録をもとに〇〇〇晃の備忘録を追加</p>
            </div>
        </div>
        <div id="bgmwak">
            <div id="btndsp">
                <button id="foldsel" onClick="ongpasget()"><b></b></button>
                <input type="file" webkitdirectory directory multiple onChange="ongfileListDirectory(this.files)" id="ongfilselct" style="display:none;">
                <button id="ongfldbtn" onClick="ongfldsel()"></button>
                <button id="playstrt" onClick="lisnkai()"></button>
                <button id="playstop" onClick="lisntei()"><b></b></button>
                <button id="playback" onClick="ongmodoru()"></button>
                <button onClick="ongvoludai()"><b></b></button>
                <button onClick="ongvolusyo()"><b></b></button>
            </div>
            <div id="ongpas">
                folder未選択
            </div>
            <canvas id="canvs" width="160" height="2"></canvas>
        </div>
    </div>
    <div id="iframewak">
        <iframe id="ifrmencont" name="ifram" src="" frameborder="0" scrolling="no"></iframe>
    </div>
  </body>
</html>

-----子ページのソースコード(kousin分)
<!DOCTYPE html>
<html lang="ja">
  <head>
    <base target="_top">
    <?!= HtmlService.createHtmlOutputFromFile('Css').getContent(); ?> <!-- css読込 -->
  </head>
  <script type="text/javascript">
    function openURL(url) {
        var gglURL = "https://script.google.com/macros/s/AKfycbxQOayD1oYR8kFXeFRHSzlXMJSicQvQdEvVA0yJ_SiRydfPmr2B/exec?p="; //googleベースURL
        var praURL = gglURL + url; //ファイル名のパラメータ追加
//        location.href = praURL; //子ページから直接読込
//        window.parent.document.getElementById('ifrmencont').src = praURL; //iframeのsrcに設定:エラーになる
        window.frameElement.src = praURL; //親ページから関節読込(iframeのsrcに設定)
    }
  </script>
  <body>
    <div id="menconwak">
        <div id="menuwaku">
            <ul>
                <li class="midasi">家系図</li>
                <li><button class="lnkbar" onclick="openURL('YotuKakeizu')">〇〇〇家</button></li>
                <li><button class="lnkbar" onclick="openURL('AbeKakeizu')"✕✕家</button></li>
                       |
                    他のメニュー
                       |
                <li><button class="lnkbar" onclick="openURL('Help')"><b>操作説明</b></button></li>
            </ul>
        </div>
        <div id="contwaku">
            <div id="content">
                <h2>更新履歴</h2>
                <br>
                <p id="rireki">
                     |
                  更新履歴内容
                     |
                </p>
            </div>
        </div>
    </div>
  </body>
</html>

-----doGet関数のソースコード
function doGet(e){
  var page = e.parameter["p"];
  if(page == "index" || page == null){
    var htmlOutput = HtmlService.createTemplateFromFile("index").evaluate();
    return htmlOutput;
  }
  else if(page == "kousin"){
    var htmloutput = HtmlService.createTemplateFromFile('kousin').evaluate();
    htmloutput.setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
    return htmloutput;
  }
  else if(page == "YotuKakeizu"){
    var htmloutput = HtmlService.createTemplateFromFile('YotuKakeizu').evaluate();
    htmloutput.setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
    return htmloutput;
  }
                       |
                    メニュー分
                       |
}
### 試したこと

ここに言語を入力

調べたこと--------------------------------------------------------
1.リンク方法を親ページからでなく直接子ページからリンクする方法を試しました。
  location.href = URL
ですが➁と同じく真白になります。
2.そこで➁の状態でデベロッパー(F12)でソースを確認しました。
GASのソースはあまりにも巨大で自分のソースが見当たりません。
Elementsでインフレームを選択して<html>を見ると何とソースが空でした。
親ページの<iframe src=""はメニューで選択したURLに書換られてます
比較のため➀と➁を同じファイルにしてGASのソースを比較しました。
同じように見えますが➁はインデントのブロックが1つ多くなっています。
これでは読込でも何も表示できません、
リンク方法もdoGet関数も全く同じでなぜこうなるのか。
何か思い違いがあるかもしれません。何が悪いのか宜しくお願いします。


```

補足情報(FW/ツールのバージョンなど)

使用ブラウザはchromeの最新バージョン。
開発はGooglrDriveのScriptEdter。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • 退会済みユーザー

    退会済みユーザー

    2019/01/22 21:07

    質問内容がいまいち理解できないです。
    これは「iframeのsrcを新しいurlに書き換えたが、そのurlのコンテンツが表示されない」という意味でしょうか?質問がその意味合いならこのサイトが参考になるかと思います。https://qiita.com/nntsugu/items/640762a7ba8fd7cc50dd
    "iframeの中身を差し替えたい場合は、location.srcを書き換えてlocation.reloadしてもダメ。
    location.replaceしましょう。"

    キャンセル

  • yotuya

    2019/01/23 03:16

    目に縮めていただきありがとうございます。前回の回答ありがとうございました。おかげさまでBGMが聞くことができ、インフレームに子ページを表示することができました。
    次に挑戦したのは子ページにあるメニューで選択したページを、同じインフレームに表示する事です。
    その時に起きた問題が今回の質問です。
    >これは「iframeのsrcを新しいurlに書き換えたが、そのurlのコンテンツが表示されない」という意味でしょうか?
    その通りです。同じリンク方法なのに帰ってきたソースには、私のHTMLソースが記述されていません。
    紹介のサイトを参考に試してみます。
    追伸
    他にも画像と音楽を同時スライドするHTMLもGAS化したのですが行き詰っていました。でも前回の回答で画像も表示できるようになりました。サーバー起動なので使いかってが本当によくなりました。ありがとうございました。

    キャンセル

  • yotuya

    2019/01/25 15:15

    早速紹介のサイトを参考に試してみました。
    iframeに子ページを表示するscriptは
     window.frameElement.contentDocument.location.replace(praURL);で
    praURLはGASのベースURL+表示ファイル名のパラメータです。
    window.frameElementにしたのは
     Window.parent.document.getElementById('ifrmencont')[0]または
     Window.parent.document.getElementById('ifrmencont')では
    scriptErroになるため、最初に使っていたframeElementにしました。
    その結果は読込んでいますがインフレームは真白になります。
    window.location.replace(praURL);
    でも試しましたが同じです。
    F12で調べると以前と同じく表示するHTMLが空です。
    ただ<scriptタグの中にcssとscriptとbodyソースが押し込まれています。
    だから読込んでいるのにHTMLが空なので表示できないと思います。
    検索キーワードが分かったので調べていますが解決には至りません。
    window.openのウィンドウでは<a href=で切替表示できますが、
    iframeでは出ないgoogleメッセージが出てしまいます。
    DOM操作でそれを表示する要素を削除しようとしましたが、
    削除できません。googleが保護しているのでしょうか。
    これが解決できればwindow.openでもいいのですが。
    何か間違いがあるでしょうか?。

    キャンセル

回答 2

checkベストアンサー

+1

試してみました。やりたいことは以下のような事ですか?

function doGet(e){
  var page = e.parameter["p"];
  if(page == "index" || page == null){
    var htmlOutput = HtmlService.createTemplateFromFile("index.html").evaluate();
    return htmlOutput;
  }
  else if(page == "a"){
    var htmloutput = HtmlService.createTemplateFromFile('a.html').evaluate();
    htmloutput.setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
    return htmloutput;
  }
  else if(page == "b"){
    var htmloutput = HtmlService.createTemplateFromFile('b.html').evaluate();
    htmloutput.setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
    return htmloutput;
  }
}
ファイル名:index.html

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
  </head>
  <body onload="openURL('a')">
    index
    <div>
            <ul>
                <li><button onclick="openURL('a')">a</button></li>
                <li><button onclick="openURL('b')">b</button></li>
            </ul>
        </div>
    <iframe id="ifrmencont" name="ifram" src="" frameborder="0" scrolling="no"></iframe>
     <script type="text/javascript">
    function openURL(url) {
        var gglURL = "https://script.google.com/macros/s/AKfycbwyzkUAatP4KABhkXs7zn0SIwFMfrdJ9GEWokWhv-11ySHR191N/exec?p="; //googleベースURL
        var praURL = gglURL + url; //ファイル名のパラメータ追加
        document.getElementById('ifrmencont').src = praURL; //iframeのsrcに設定
        document.getElementById('ifrmencont').contentWindow.location.replace(praURL);
        console.log(praURL);
    }
  </script>
  </body>
</html>
ファイル名:a.html

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
  </head>
  <body>
    aaa
  </body>
</html>
ファイル名:b.html

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
  </head>
  <body>
    bbb
  </body>
</html>


補足:location.replaceはあってもなくても動作が一緒でした。(ボタンをおすごとにiframeの内容が切り替わる)


回答追加 1/29 12:30

子要素から親要素を編集したいということでしたので修正しました。

ファイル名:コード.gs

function doGet(e){
  var page = e.parameter["p"];
  if(page == "index" || page == null){
    var htmlOutput = HtmlService.createTemplateFromFile("index.html").evaluate();
    return htmlOutput;
  }
  else if(page == "a"){
    var htmloutput = HtmlService.createTemplateFromFile('a.html').evaluate();
    htmloutput.setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
    return htmloutput;
  }
  else if(page == "b"){
    var htmloutput = HtmlService.createTemplateFromFile('b.html').evaluate();
    htmloutput.setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
    return htmloutput;
  }
}
ファイル名:index.html

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
  </head>
  <body>
    index

    <iframe id="ifrmencont" src="https://script.google.com/macros/s/AKfycbwyzkUAatP4KABhkXs7zn0SIwFMfrdJ9GEWokWhv-11ySHR191N/exec?p=a" frameborder="0" scrolling="no"></iframe>
  </body>
</html>
ファイル名:a.html

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
  </head>
  <body>
  aaaaaaaaaaaaaaa
        <div>
    menu
            <ul>
                <li><button onclick="openUrl('a')">ページa</button></li>
                <li><button onclick="openUrl('b')">ページb</button></li>
            </ul>
        </div>
        <script>
        function openUrl(param){
          var ifrmencont = window.parent.parent.parent.document.getElementById('ifrmencont');
          console.log(ifrmencont);
          ifrmencont.src = 'https://script.google.com/macros/s/AKfycbwyzkUAatP4KABhkXs7zn0SIwFMfrdJ9GEWokWhv-11ySHR191N/exec?p=' + param;
        }
        </script>
  </body>
</html>
ファイル名:b.html

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
  </head>
  <body>
  bbbbbbbbbbbbbbb
        <div>
    menu
            <ul>
                <li><button onclick="openUrl('a')">ページa</button></li>
                <li><button onclick="openUrl('b')">ページb</button></li>
            </ul>
        </div>
        <script>
        function openUrl(param){
          var ifrmencont = window.parent.parent.parent.document.getElementById('ifrmencont');
          console.log(ifrmencont);
          ifrmencont.src = 'https://script.google.com/macros/s/AKfycbwyzkUAatP4KABhkXs7zn0SIwFMfrdJ9GEWokWhv-11ySHR191N/exec?p=' + param;
        }
        </script>
  </body>
</html>

回答追加 1/29 15:30

「なぜparentが三つなのか?」
chromeブラウザの検証ツールで確認できます。
実際に見てみるとiframeが何重にもなっているのが分かります。
iframe確認

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/02/01 05:18

    > なので今回も回答のサンプル少しづつ追加していき、どこでおかしくなるか切り分けようと思います。
    そうですね。プログラミングはそういった地道な作業が大事だと思います。次からは問題が発生したら、問題部分に特化した(他の機能は全て省いた)最小構成のサンプルコード作成に取り組むようにしてください。そして、そのサンプルコードが動かなかった時にteratailで「サンプルコードが動かない」と質問するようにしてください。それはpapinianusさんの言う「問題の限定・抽象化」に繋がることです。ソースに余計な部分がないので読みやすく、質問内容が理解されやすいと思います。

    キャンセル

  • 2019/02/01 20:39

    作業は進んでほぼ終わる手前ですが、作業中にふっとひらめきました。
    parent×3で子ページから親ページの関数を実行できるのではないか。
    期待に胸膨らませ試したところ見事に実行することができました。
    これなら子の参照ボタンから親のメニューの強調表示ができます。
    作業は中止してメニューをindexに戻したプロジェクトに戻ります。
    修正の必要な5ファイルに参照ボタンと関数実行を追加するだけです。
    今後メニューの追加は楽になり子ページのソースもスッキリします。
    これは完全な解決です。ベストアンサーを差し上げたく問合せ中です。
    これで開発当初から考えていた構成で備忘録が完成します。
    BGMを聴きながら家族写真や誕生からの記録を見ることができます。
    ありがとうございました。
    ただgoogleのEdterでコンテンツのメンテはチョットきついですね。

    キャンセル

  • 2019/02/04 18:09

    結果的にはメニューはindexに戻しましたが、a,bからのメニュー選択(参照リンク)とメニュー名の強調表示が可能になりました。自己解決の取消方法が分かりましたので、ベストアンサーとすることができました。ありがとうございました。

    キャンセル

0

投稿した後に回答で無事解決したので削除しました。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/01/31 14:24 編集

    > この質問の閲覧者が大勢いるのは同じような問題を抱えている人が大勢いるということだと思います
    ビュワーとしてコメントします。要約されるのを待っていました。
    特殊・具体的な方向に深化するほど、質問は特定の質問者様の個人的な問題に帰着し、そのモノを見せてください、みたいな話にしかなりませんし、それではGASの顧客サポートです。
    もっと問題を限定・抽象化して、「他の同じ問題で困っていそうな人」が出てくるレベルにしていただかないと、teratailでは回答はつきにくいと思います。この点、NETACHIL様の最初のコメント「質問内容がいまいち理解できないです」に尽きています。

    目的に対するアプローチで考えますと。
    GASがwebサーバとして特殊である、GETのターンアラウンドタイムが長いはそのとおりで、特有の苦労をするに値しないものであれば、他のサーバをかりたり、個人用途なら自宅PCをサーバ公開してもいいはず(今どき、ルータの機能でVPNができたりするので)です。
    (あくまで見解であって、批判の意図はないです)

    キャンセル

  • 2019/01/31 15:59

    ・確か以前にもコメントがありましたね。見解ありがとうございます。テラテイルをはじめWebに質問したのは初めてです。だからといって言い訳はしませんが。自分としては少しでも理解しやすいようにと思って、ついつい説明が多く長くなってしまいました。でもNETACHIL様とpapinianus様のご指摘のように、自分でも論点が分かりずらくなっているなと感じていました。逆効果ですね。それと不確かな自分の見解も不要ですね。この点を踏まえてこれからもテラテイルの力を借りたいと思います。宜しくお願いします。
    ・またサーバーについては、以前に作成したHTMLのローカル起動に満足できづ、WindowsのIISを考たこともありましたが、いまだに実現できずにGASを利用しました。でもIIS以外にもPCをサーバーにするソフトはあり、chromeの拡張機能でも実現できるようなので考えてみます。私が作るWebアプリケーションは小さなツール系なので疑似サーバーで十分です。後押しになりました。ありがとうございます。

    キャンセル

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

  • ただいまの回答率 87.61%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る