プルダウンで自作htmlがiframeで表示位置を固定して、読込先のページ数に応じて親ページの高さを変えたいです。
解決したいこと
プルダウンで自作htmlがiframeで表示位置を固定して、iframeを可変サイズとして、それに応じて、親ページの高さを変えたいです。
現状iframeを用いていますが、
これには訳があり、iframeを用いない方法を用いますと、htmlの保護規定によりdom設定しない限り、
直リンクができないしようとなっており、そのための環境設定が難しいためです。
一方、iframe自体のページサイズは大きくできても、
親ファイルのページサイズをiframeによって変更できないのが苦しい実態です。
解決策はないのでしょうか?
例)
Ruby on RailsでQiitaのようなWebアプリをつくっています。
記事を投稿する機能の実装中にエラーが発生しました。
解決方法を教えて下さい。
発生している問題・エラー
出ているエラーメッセージを入力
例)
該当するソースコード
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>5階層プルダウン (HTML完結)</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<style>
select {
margin: 5px;
padding: 8px;
border: 1px solid #ccc;
border-radius: 4px;
font-size: 1rem;
width: 200px;
}
</style>
<style>
body {
margin: 0; /* 追加: bodyの余白をなくす */
padding: 0; /* 追加: bodyのパディングをなくす */
/* overflow: hidden; */ /* 今回は親HTMLが延長する方式なので不要、または除去 */
}
iframe {
width: 100vw;
height: 100vh;
border: none;
overflow: hidden;
}
</style>
</head>
<body>
<h1>5階層プルダウンメニュー (HTML完結)</h1>
<select id="level1">
<option value="">選択してください</option>
<option value="JR">JR</option>
<option value="大手私鉄">大手私鉄</option>
<option value="高速バスその他">高速バスその他</option>
</select>
<select id="level2" disabled>
<option value="">選択してください</option>
<option value="新幹線" data-parent="JR">新幹線</option>
<option value="JR北海道" data-parent="JR">JR北海道</option>
<option value="JR東日本" data-parent="JR">JR東日本</option>
<option value="JR東海" data-parent="JR">JR東海</option>
<option value="JR西日本" data-parent="JR">JR西日本</option>
<option value="JR四国" data-parent="JR">JR四国</option>
<option value="JR九州" data-parent="JR">JR九州</option>
</select>
<select id="level3" disabled>
<option value="">選択してください</option>
<option value="東北・北海道・山形・秋田新幹線" data-parent="新幹線">東北・北海道・山形・秋田新幹線</option>
<option value="上越・北陸新幹線" data-parent="新幹線">上越・北陸新幹線</option>
<option value="東海道・山陽新幹線" data-parent="新幹線">東海道・山陽新幹線</option>
<option value="九州・西九州新幹線" data-parent="新幹線">九州・西九州新幹線</option>
<option value="北海道地区" data-parent="JR北海道">北海道地区</option>
<option value="首都圏各線" data-parent="JR東日本">首都圏各線</option>
<option value="中央本線系統" data-parent="JR東日本">中央本線系統</option>
<option value="上信越線系統" data-parent="JR東日本">上信越線系統</option>
<option value="東北地区" data-parent="JR東日本">東北地区</option>
<option value="東海地区" data-parent="JR東海">東海地区</option>
<option value="北陸地区" data-parent="JR西日本">北陸地区</option>
<option value="nagoya" data-parent="aichi">名古屋市</option>
</select>
<select id="level4" disabled>
<option value="">選択してください</option>
<option value="はやぶさ(現役、新幹線時代)" data-parent="東北・北海道・山形・秋田新幹線">はやぶさ(現役、新幹線時代)</option>
<option value="はやて(現役)" data-parent="東北・北海道・山形・秋田新幹線">はやて(現役)</option>
<option value="こまち(現役)" data-parent="東北・北海道・山形・秋田新幹線">こまち(現役)</option>
<option value="サンダーバード(現役)" data-parent="北陸地区">特急 サンダーバード(現役)</option>
<option value="しらさぎ(現役)" data-parent="北陸地区">特急 しらさぎ(現役)</option>
<option value="能登かがり火(現役)" data-parent="北陸地区">特急 能登かがり火(現役)</option>
<option value="花嫁のれん(現役、臨時列車)" data-parent="北陸地区">特急 花嫁のれん(現役、臨時列車)</option>
<option value="べるもんた(現役、臨時列車)" data-parent="北陸地区">快速 ベル・モンターユ・エ・メール(べるもんた) (現役、臨時列車)</option>
<option value="スーパー雷鳥(退役)" data-parent="北陸地区">特急 スーパー雷鳥(退役)</option>
<option value="雷鳥(退役)" data-parent="北陸地区">特急 雷鳥(退役)</option>
<option value="白鳥(退役)" data-parent="北陸地区">特急 白鳥(退役)</option>
<option value="加越(退役)" data-parent="北陸地区">特急 加越(退役)</option>
<option value="はくたか(退役、在来線時代)" data-parent="北陸地区">特急 はくたか(退役、在来線時代)</option>
<option value="北越(退役)" data-parent="北陸地区">特急 北越(退役)</option>
<option value="急行能登(退役)" data-parent="北陸地区">急行 能登(退役)</option>
</select>
<select id="level5" disabled>
<option value="">選択してください</option>
<optgroup label="19971001ダイヤ改正">
<option value="19971001現在編成-スーパー雷鳥1001A" data-parent="スーパー雷鳥(退役)" data-url="座席表/JR西日本/19971001現在 スーパー雷鳥1001A 20250728 Mon.html">しらさぎ編成その1</option>
<option value="19971001現在編成-スーパー雷鳥1002A" data-parent="スーパー雷鳥(退役)" data-url="座席表/JR西日本/19971001現在 スーパー雷鳥1002A 20250728 Mon.html">しらさぎ編成その2パターンA</option>
<option value="19971001現在編成-雷鳥1001A" data-parent="雷鳥(退役)" data-url="座席表/JR西日本/19971001現在 雷鳥1001A 20250728 Mon.html">しらさぎ編成その1</option>
<option value="19971001現在編成-雷鳥1002A" data-parent="雷鳥(退役)" data-url="座席表/JR西日本/19971001現在 雷鳥1001B 20250728 Mon.html">しらさぎ編成その2パターンA</option>
</select>
<div id="contentDisplay" style="margin-top: 20px;">
<p>ここに選択されたコンテンツが表示されます。</p>
<button id="resetSelection">選択を初期化</button>
<iframe id="dynamicIframe" src=""></iframe>
</div>
<style>
select {
margin: 5px;
padding: 8px;
border: 1px solid #ccc;
border-radius: 4px;
font-size: 1rem;
width: 200px;
}
body {
margin: 0;
padding: 0;
/* overflow: hidden; */
}
iframe {
width: 100vw;
height: 100vh;
border: none;
overflow: hidden;
}
iframe {
border: none;
display: block;
margin: 0 auto;
overflow: hidden;
}
</style>
<script>
$(document).ready(function() {
/**
* 次の階層以降のプルダウンをリセットし、無効化、オプションを非表示にする
* @param {number} startLevel - リセットを開始する階層の番号
*/
function resetNextLevels(startLevel) {
for (let i = startLevel; i <= 5; i++) { // 階層の最大値を5に合わせる
const $currentSelect = $(`#level${i}`);
$currentSelect.val(''); // 選択をクリア
// level1 以外は無効化、またはstartLevelが2以上の場合は無効化
if (i > 1 || startLevel > 1) { // level1は常に有効にする
$currentSelect.prop('disabled', true);
} else {
$currentSelect.prop('disabled', false); // level1は有効のまま
}
// level1 以外のオプションを非表示にする(選択してください、以外)
// i === 1 (level1) の場合は、オプションを非表示にしないようにする
if (i > 1) {
$currentSelect.find('option:not([value=""])').hide();
}
}
}
/**
* 指定されたプルダウンの関連オプションを表示し、有効化する
* @param {string} selector - プルダウンのCSSセレクタ (例: '#level2')
* @param {string} parentValue - 親のプルダウンで選択された値
*/
function showRelatedOptions(selector, parentValue) {
const $select = $(selector);
$select.prop('disabled', false); // プルダウンを有効化
// 親の値に紐づくオプションを表示
$select.find(`option[data-parent="${parentValue}"]`).show();
// 「選択してください」オプションも表示しておく
$select.find('option[value=""]').show();
}
// 初期状態: level2 から level5 までのオプションを全て非表示にし、プルダウンを無効化
resetNextLevels(2); // level2以降をリセットし無効化
// 初期ロード時にlevel1を明示的に有効にする(念のため)
$('#level1').prop('disabled', false);
// level1の全オプションを表示する(初期状態では非表示になっていないはずだが、念のため)
$('#level1').find('option').show();
// --- イベントリスナーの設定 ---
$('#level1').on('change', function() {
const selectedParent = $(this).val();
resetNextLevels(2); // level2以降をリセット
$('#dynamicIframe').attr('src', '').hide(); // iframeをクリア
$('#contentDisplay p').show(); // 初期メッセージを表示
if (selectedParent) {
showRelatedOptions('#level2', selectedParent);
}
});
$('#level2').on('change', function() {
const selectedParent = $(this).val();
resetNextLevels(3);
$('#dynamicIframe').attr('src', '').hide(); // iframeをクリア
$('#contentDisplay p').show(); // 初期メッセージを表示
if (selectedParent) {
showRelatedOptions('#level3', selectedParent);
}
});
$('#level3').on('change', function() {
const selectedParent = $(this).val();
resetNextLevels(4);
$('#dynamicIframe').attr('src', '').hide(); // iframeをクリア
$('#contentDisplay p').show(); // 初期メッセージを表示
if (selectedParent) {
showRelatedOptions('#level4', selectedParent);
}
});
$('#level4').on('change', function() {
const selectedParent = $(this).val();
resetNextLevels(5);
$('#dynamicIframe').attr('src', '').hide(); // iframeをクリア
$('#contentDisplay p').show(); // 初期メッセージを表示
if (selectedParent) {
showRelatedOptions('#level5', selectedParent);
}
});
// level5 の変更イベント (iframe表示に変更)
$('#level5').on('change', function() {
const selectedOption = $(this).find('option:selected');
const finalSelectionValue = selectedOption.val();
const targetUrl = selectedOption.data('url');
const $dynamicIframe = $('#dynamicIframe');
const $contentDisplayMessage = $('#contentDisplay p');
if (targetUrl) {
$contentDisplayMessage.hide();
$dynamicIframe.attr('src', targetUrl).show();
console.log("選択されたURLをiframeに表示:", targetUrl);
// iframeのロード完了時に高さを調整
$dynamicIframe.off('load').on('load', function() {
try {
// 同じオリジンのコンテンツのみアクセス可能
const iframeContentHeight = this.contentWindow.document.body.scrollHeight;
$(this).css('height', iframeContentHeight + 'px');
console.log("iframeの高さを調整:", iframeContentHeight + "px");
} catch (e) {
console.warn("iframeのコンテンツにアクセスできません。異なるオリジンである可能性があります。", e);
// 異なるオリジンの場合は、固定の高さに戻すか、スクロールを許可するなどの対応
$(this).css('height', '100vh'); // あるいは、適切なデフォルト値
}
});
} else {
$dynamicIframe.attr('src', '').hide();
$dynamicIframe.css('height', '100vh'); // iframeをクリアしたら元の高さに戻すか、適切なデフォルト値
$contentDisplayMessage.show();
console.log("iframe表示クリア");
}
});
// 「選択を初期化」ボタンのクリックイベントリスナー
$('#resetSelection').on('click', function() {
resetNextLevels(1); // 全てのレベルをリセット(level1も含む)
$('#level1').prop('disabled', false); // level1を明示的に有効にする
$('#level1').find('option').show(); // level1の全オプションを表示
$('#dynamicIframe').attr('src', '').hide(); // iframeをクリア
$('#contentDisplay p').show(); // 初期メッセージを表示
});
});
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>5階層プルダウン (HTML完結)</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<style>
select {
margin: 5px;
padding: 8px;
border: 1px solid #ccc;
border-radius: 4px;
font-size: 1rem;
width: 200px;
}
</style>
<style>
body {
margin: 0; /* 追加: bodyの余白をなくす */
padding: 0; /* 追加: bodyのパディングをなくす */
/* overflow: hidden; */ /* 今回は親HTMLが延長する方式なので不要、または除去 */
}
iframe {
width: 100vw;
height: 100vh;
border: none;
overflow: hidden;
}
</style>
</head>
<body>
<h1>5階層プルダウンメニュー (HTML完結)</h1>
<select id="level1">
<option value="">選択してください</option>
<option value="JR">JR</option>
<option value="大手私鉄">大手私鉄</option>
<option value="高速バスその他">高速バスその他</option>
</select>
<select id="level2" disabled>
<option value="">選択してください</option>
<option value="新幹線" data-parent="JR">新幹線</option>
<option value="JR北海道" data-parent="JR">JR北海道</option>
<option value="JR東日本" data-parent="JR">JR東日本</option>
<option value="JR東海" data-parent="JR">JR東海</option>
<option value="JR西日本" data-parent="JR">JR西日本</option>
<option value="JR四国" data-parent="JR">JR四国</option>
<option value="JR九州" data-parent="JR">JR九州</option>
</select>
<select id="level3" disabled>
<option value="">選択してください</option>
<option value="東北・北海道・山形・秋田新幹線" data-parent="新幹線">東北・北海道・山形・秋田新幹線</option>
<option value="上越・北陸新幹線" data-parent="新幹線">上越・北陸新幹線</option>
<option value="東海道・山陽新幹線" data-parent="新幹線">東海道・山陽新幹線</option>
<option value="九州・西九州新幹線" data-parent="新幹線">九州・西九州新幹線</option>
<option value="北海道地区" data-parent="JR北海道">北海道地区</option>
<option value="首都圏各線" data-parent="JR東日本">首都圏各線</option>
<option value="中央本線系統" data-parent="JR東日本">中央本線系統</option>
<option value="上信越線系統" data-parent="JR東日本">上信越線系統</option>
<option value="東北地区" data-parent="JR東日本">東北地区</option>
<option value="東海地区" data-parent="JR東海">東海地区</option>
<option value="北陸地区" data-parent="JR西日本">北陸地区</option>
<option value="nagoya" data-parent="aichi">名古屋市</option>
</select>
<select id="level4" disabled>
<option value="">選択してください</option>
<option value="">選択してください</option>
<option value="はやぶさ(現役、新幹線時代)" data-parent="東北・北海道・山形・秋田新幹線">はやぶさ(現役、新幹線時代)</option>
<option value="はやて(現役)" data-parent="東北・北海道・山形・秋田新幹線">はやて(現役)</option>
<option value="こまち(現役)" data-parent="東北・北海道・山形・秋田新幹線">こまち(現役)</option>
<option value="サンダーバード(現役)" data-parent="北陸地区">特急 サンダーバード(現役)</option>
<option value="しらさぎ(現役)" data-parent="北陸地区">特急 しらさぎ(現役)</option>
<option value="能登かがり火(現役)" data-parent="北陸地区">特急 能登かがり火(現役)</option>
<option value="花嫁のれん(現役、臨時列車)" data-parent="北陸地区">特急 花嫁のれん(現役、臨時列車)</option>
<option value="べるもんた(現役、臨時列車)" data-parent="北陸地区">快速 ベル・モンターユ・エ・メール(べるもんた) (現役、臨時列車)</option>
<option value="スーパー雷鳥(退役)" data-parent="北陸地区">特急 スーパー雷鳥(退役)</option>
<option value="雷鳥(退役)" data-parent="北陸地区">特急 雷鳥(退役)</option>
<option value="白鳥(退役)" data-parent="北陸地区">特急 白鳥(退役)</option>
<option value="加越(退役)" data-parent="北陸地区">特急 加越(退役)</option>
<option value="はくたか(退役、在来線時代)" data-parent="北陸地区">特急 はくたか(退役、在来線時代)</option>
<option value="北越(退役)" data-parent="北陸地区">特急 北越(退役)</option>
<option value="急行能登(退役)" data-parent="北陸地区">急行 能登(退役)</option>
</select>
<select id="level5" disabled>
<option value="">選択してください</option>
<optgroup label="19971001ダイヤ改正">
<option value="19971001現在編成-スーパー雷鳥1001A" data-parent="スーパー雷鳥(退役)" data-url="座席表/JR西日本/19971001現在 スーパー雷鳥1001A 20250728 Mon.html">しらさぎ編成その1</option>
<option value="19971001現在編成-スーパー雷鳥1002A" data-parent="スーパー雷鳥(退役)" data-url="座席表/JR西日本/19971001現在 スーパー雷鳥1002A 20250728 Mon.html">しらさぎ編成その2パターンA</option>
<option value="19971001現在編成-雷鳥1001A" data-parent="雷鳥(退役)" data-url="座席表/JR西日本/19971001現在 雷鳥1001A 20250728 Mon.html">しらさぎ編成その1</option>
<option value="19971001現在編成-雷鳥1002A" data-parent="雷鳥(退役)" data-url="座席表/JR西日本/19971001現在 雷鳥1001B 20250728 Mon.html">しらさぎ編成その2パターンA</option>
</select>
<div id="contentDisplay" style="margin-top: 20px;">
<p>ここに選択されたコンテンツが表示されます。</p>
<button id="resetSelection">選択を初期化</button>
<iframe id="dynamicIframe" src=""></iframe>
</div>
<style>
select {
margin: 5px;
padding: 8px;
border: 1px solid #ccc;
border-radius: 4px;
font-size: 1rem;
width: 200px;
}
body {
margin: 0;
padding: 0;
/* overflow: hidden; */
}
iframe {
width: 100vw;
height: 100vh;
border: none;
overflow: hidden;
}
iframe {
border: none;
display: block;
margin: 0 auto;
overflow: hidden;
}
</style>
<script>
$(document).ready(function() {
/**
* 次の階層以降のプルダウンをリセットし、無効化、オプションを非表示にする
* @param {number} startLevel - リセットを開始する階層の番号
*/
function resetNextLevels(startLevel) {
for (let i = startLevel; i <= 5; i++) { // 階層の最大値を5に合わせる
const $currentSelect = $(`#level${i}`);
$currentSelect.val(''); // 選択をクリア
// level1 以外は無効化、またはstartLevelが2以上の場合は無効化
if (i > 1 || startLevel > 1) { // level1は常に有効にする
$currentSelect.prop('disabled', true);
} else {
$currentSelect.prop('disabled', false); // level1は有効のまま
}
// level1 以外のオプションを非表示にする(選択してください、以外)
// i === 1 (level1) の場合は、オプションを非表示にしないようにする
if (i > 1) {
$currentSelect.find('option:not([value=""])').hide();
}
}
}
/**
* 指定されたプルダウンの関連オプションを表示し、有効化する
* @param {string} selector - プルダウンのCSSセレクタ (例: '#level2')
* @param {string} parentValue - 親のプルダウンで選択された値
*/
function showRelatedOptions(selector, parentValue) {
const $select = $(selector);
$select.prop('disabled', false); // プルダウンを有効化
// 親の値に紐づくオプションを表示
$select.find(`option[data-parent="${parentValue}"]`).show();
// 「選択してください」オプションも表示しておく
$select.find('option[value=""]').show();
}
// 初期状態: level2 から level5 までのオプションを全て非表示にし、プルダウンを無効化
resetNextLevels(2); // level2以降をリセットし無効化
// 初期ロード時にlevel1を明示的に有効にする(念のため)
$('#level1').prop('disabled', false);
// level1の全オプションを表示する(初期状態では非表示になっていないはずだが、念のため)
$('#level1').find('option').show();
// --- イベントリスナーの設定 ---
$('#level1').on('change', function() {
const selectedParent = $(this).val();
resetNextLevels(2); // level2以降をリセット
$('#dynamicIframe').attr('src', '').hide(); // iframeをクリア
$('#contentDisplay p').show(); // 初期メッセージを表示
if (selectedParent) {
showRelatedOptions('#level2', selectedParent);
}
});
$('#level2').on('change', function() {
const selectedParent = $(this).val();
resetNextLevels(3);
$('#dynamicIframe').attr('src', '').hide(); // iframeをクリア
$('#contentDisplay p').show(); // 初期メッセージを表示
if (selectedParent) {
showRelatedOptions('#level3', selectedParent);
}
});
$('#level3').on('change', function() {
const selectedParent = $(this).val();
resetNextLevels(4);
$('#dynamicIframe').attr('src', '').hide(); // iframeをクリア
$('#contentDisplay p').show(); // 初期メッセージを表示
if (selectedParent) {
showRelatedOptions('#level4', selectedParent);
}
});
$('#level4').on('change', function() {
const selectedParent = $(this).val();
resetNextLevels(5);
$('#dynamicIframe').attr('src', '').hide(); // iframeをクリア
$('#contentDisplay p').show(); // 初期メッセージを表示
if (selectedParent) {
showRelatedOptions('#level5', selectedParent);
}
});
// level5 の変更イベント (iframe表示に変更)
$('#level5').on('change', function() {
const selectedOption = $(this).find('option:selected');
const finalSelectionValue = selectedOption.val();
const targetUrl = selectedOption.data('url');
const $dynamicIframe = $('#dynamicIframe');
const $contentDisplayMessage = $('#contentDisplay p');
if (targetUrl) {
$contentDisplayMessage.hide();
$dynamicIframe.attr('src', targetUrl).show();
console.log("選択されたURLをiframeに表示:", targetUrl);
// iframeのロード完了時に高さを調整
$dynamicIframe.off('load').on('load', function() {
try {
// 同じオリジンのコンテンツのみアクセス可能
const iframeContentHeight = this.contentWindow.document.body.scrollHeight;
$(this).css('height', iframeContentHeight + 'px');
console.log("iframeの高さを調整:", iframeContentHeight + "px");
} catch (e) {
console.warn("iframeのコンテンツにアクセスできません。異なるオリジンである可能性があります。", e);
// 異なるオリジンの場合は、固定の高さに戻すか、スクロールを許可するなどの対応
$(this).css('height', '100vh'); // あるいは、適切なデフォルト値
}
});
} else {
$dynamicIframe.attr('src', '').hide();
$dynamicIframe.css('height', '100vh'); // iframeをクリアしたら元の高さに戻すか、適切なデフォルト値
$contentDisplayMessage.show();
console.log("iframe表示クリア");
}
});
// 「選択を初期化」ボタンのクリックイベントリスナー
$('#resetSelection').on('click', function() {
resetNextLevels(1); // 全てのレベルをリセット(level1も含む)
$('#level1').prop('disabled', false); // level1を明示的に有効にする
$('#level1').find('option').show(); // level1の全オプションを表示
$('#dynamicIframe').attr('src', '').hide(); // iframeをクリア
$('#contentDisplay p').show(); // 初期メッセージを表示
});
});
</script>
</body>
</html>
例)
def greet
puts Hello World
end
自分で試したこと
ここに問題・エラーに対して試したことを記載してください。
htmlで先に説明した2案を試したり、
geminiなどの生成aiを使用してみたりしましたが、有効な回答は得られず、
泣き寝入りの状態です。
どうしたらいいでしょうか?


