<!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 |