junkerstock
 tt-test5 

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>画像選択デモ (折りたたみ機能付き)</title>
<style>
/* 全体のスタイル */
body {
font-family: sans-serif;
margin: 20px;
}

/* 画像を並べるコンテナのスタイル */
#image-container {
display: flex; /* 画像を横に並べる */
flex-wrap: wrap; /* 画面幅で折り返す */
gap: 15px; /* 画像間のスペース */
margin-bottom: 20px;
}

/* 各画像とそのタイトルのコンテナ */
.image-item {
text-align: center; /* タイトルを中央揃えに */
cursor: pointer; /* クリックできることを示すカーソル */
border: 2px solid #ccc;
border-radius: 8px;
padding: 10px;
transition: all 0.2s;
/* ★折りたたみアニメーション(任意) */
transition: opacity 0.3s, transform 0.3s;
}

/* 画像自体のスタイル */
.image-item img {
width: 100px;
height: 100px;
display: block;
margin-bottom: 5px;
}

/* 選択された時のスタイル */
.image-item.selected {
border-color: #007bff; /* 枠線の色を変更 */
background-color: #e7f3ff; /* 背景色を変更 */
}

/* ★改行用の要素のスタイル (修正) */
.image-newline {
flex-basis: 100%;
margin: 0;
padding: 0;
font-weight: bold;
font-size: 1.1em;
color: #333;
margin-top: 20px;
margin-bottom: 10px;
border-bottom: 1px solid #ddd;
padding-bottom: 5px;

/* ★追加: 折りたたみのためのスタイル */
cursor: pointer; /* クリックできることを示す */
user-select: none; /* テキスト選択を無効化 */
}

/* ★追加: インジケーター (開いている状態) */
.image-newline::before {
content: '▼ '; /* スペースを入れる */
font-size: 0.9em;
color: #007bff;
}

/* ★追加: インジケーター (閉じている状態) */
.image-newline.collapsed::before {
content: '▶ '; /* スペースを入れる */
}


/* テキストエリアとボタンのコンテナ */
.output-area {
display: flex;
align-items: flex-start;
gap: 10px;
}

/* テキストボックスのスタイル */
#output-box {
width: 100%;
padding: 10px;
font-size: 16px;
box-sizing: border-box;
flex-grow: 1;
}

/* コピーボタンのスタイル */
#copy-button {
padding: 10px 15px;
font-size: 16px;
cursor: pointer;
border: 1px solid #007bff;
background-color: #007bff;
color: white;
border-radius: 5px;
transition: background-color 0.2s;
}
#copy-button:hover {
background-color: #0056b3;
}
</style>
</head>
<body>

<h1>画像を選択してください</h1>
<p>クリックで選択/選択解除できます。<br>カテゴリ名(▼)をクリックすると、そのセクションを折りたためます。</p>

<div id="image-container"></div>

<div class="output-area">
<textarea id="output-box" rows="5" placeholder="選択した画像に関連するテキストがここに表示されます..."></textarea>
<button id="copy-button">コピー</button>
</div>

<script>
// 画像のデータ
const imageData = [
{ id: 'a1', src: './pic/a1.png', title: 'タイトル A1', text: 'abcde fff' },
{ id: 'a2', src: './pic/a2.png', title: 'タイトル A2', text: 'wqqww eeew qq' },
{ id: 'a3', src: './pic/a3.png', title: 'タイトル A3', text: 'ppp' },
{ type: 'newline', text: '--- グループ B ---' },
{ id: 'b1', src: './pic/b1.png', title: 'タイトル B1', text: 'sample text 1' },
{ id: 'b2', src: './pic/b2.png', title: 'タイトル B2', text: 'hello world' },
{ id: 'b3', src: './pic/b3.png', title: 'タイトル B3', text: 'JavaScript demo' },
{ type: 'newline', text: '--- グループ C ---' },
{ id: 'c1', src: './pic/c1.png', title: 'タイトル C1', text: 'new line example' },
];

// ページが読み込まれたときに実行する処理
document.addEventListener('DOMContentLoaded', () => {
const container = document.getElementById('image-container');
const outputBox = document.getElementById('output-box');
const copyButton = document.getElementById('copy-button');

// 1. データに基づいて画像要素または改行要素をHTMLに生成する
imageData.forEach(data => {
if (data.type === 'newline') {
// 改行用の要素を挿入
const newlineDiv = document.createElement('div');
newlineDiv.classList.add('image-newline');

if (data.text) {
newlineDiv.textContent = data.text;
}
container.appendChild(newlineDiv);

// ★★★ ここからが追加部分 (折りたたみ機能) ★★★
newlineDiv.addEventListener('click', () => {
// (1) クリックされたヘッダーに 'collapsed' クラスを付け外し
newlineDiv.classList.toggle('collapsed');
const isCollapsed = newlineDiv.classList.contains('collapsed');

// (2) 次の兄弟要素から順に走査
let nextElement = newlineDiv.nextElementSibling;

while (nextElement) {
// (3) 次のヘッダー (.image-newline) が見つかったらループ停止
if (nextElement.classList.contains('image-newline')) {
break;
}

// (4) 画像アイテム (.image-item) なら
if (nextElement.classList.contains('image-item')) {
// 'collapsed' 状態なら非表示('none')、そうでなければ表示('')
nextElement.style.display = isCollapsed ? 'none' : '';
}

// (5) 次の兄弟要素へ移動
nextElement = nextElement.nextElementSibling;
}
});
// ★★★ ここまでが追加部分 ★★★

} else {
// 各画像アイテムの親要素(div)を作成
const itemDiv = document.createElement('div');
itemDiv.classList.add('image-item');
itemDiv.dataset.text = data.text;

const img = document.createElement('img');
img.src = data.src;
img.alt = data.title;

const title = document.createElement('p');
title.textContent = data.title;

itemDiv.appendChild(img);
itemDiv.appendChild(title);
container.appendChild(itemDiv);

// 2. 各画像アイテムにクリックイベントを追加する
itemDiv.addEventListener('click', () => {
itemDiv.classList.toggle('selected');
updateTextBox();
});
}
});

// 3. テキストボックスを更新する関数
function updateTextBox() {
const selectedItems = document.querySelectorAll('.image-item.selected');
const selectedTexts = Array.from(selectedItems).map(item => item.dataset.text);
outputBox.value = selectedTexts.length > 0 ? selectedTexts.join(',') + ',' : '';
}

// 4. コピーボタンにクリックイベントを追加する
copyButton.addEventListener('click', () => {
if (outputBox.value.length === 0) {
alert('コピーするテキストがありません。');
return;
}
navigator.clipboard.writeText(outputBox.value)
.then(() => {
const originalText = copyButton.textContent;
copyButton.textContent = 'コピー完了!';
setTimeout(() => {
copyButton.textContent = originalText;
}, 1500);
})
.catch(err => {
console.error('クリップボードへのコピーに失敗しました: ', err);
alert('コピーに失敗しました。');
});
});
});
</script>

</body>
</html>


使用変数

alt
charset
class
container
content
copyButton
data
display
err
id
imageData
img
isCollapsed
item
itemDiv
lang
length
name
newlineDiv
nextElement
originalText
outputBox
placeholder
rows
scale
selectedItems
selectedTexts
src
text
textContent
title
type
updateTextBox -------( Function )
value
width

Content-type: text/html error-smemo8

ERROR !

ファイルの差し替えに失敗しました: ./smemo8.log