<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ブックマークサイト</title>
<style>
:root {
--bg-color: #f4f4f9;
--text-color: #000;
--link-color: #007bff;
--btn-bg-color: #007bff;
--btn-hover-color: #0056b3;
--delete-btn-bg-color: #dc3545;
--delete-btn-hover-color: #c82333;
}
[data-theme="dark"] {
--bg-color: #2e2e2e;
--text-color: #fff;
--link-color: #66b2ff;
--btn-bg-color: #0056b3;
--btn-hover-color: #007bff;
--delete-btn-bg-color: #c82333;
--delete-btn-hover-color: #dc3545;
}
body {
font-family: Arial, sans-serif;
margin: 20px;
padding: 0;
background-color: var(--bg-color);
color: var(--text-color);
transition: background-color 0.3s, color 0.3s;
}
.container {
max-width: 800px;
margin: auto;
padding: 20px;
background: #fff;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
border-radius: 8px;
background-color: var(--bg-color);
color: var(--text-color);
transition: background-color 0.3s, color 0.3s;
}
.bookmark-form {
display: flex;
flex-direction: column;
gap: 10px;
margin-bottom: 20px;
}
.bookmark-form input, .bookmark-form select {
padding: 10px;
font-size: 16px;
border: 1px solid #ddd;
border-radius: 5px;
background-color: var(--bg-color);
color: var(--text-color);
}
.bookmark-form button {
padding: 10px;
font-size: 16px;
background-color: var(--btn-bg-color);
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
}
.bookmark-form button:hover {
background-color: var(--btn-hover-color);
}
.bookmark-list {
list-style-type: none;
padding: 0;
}
.bookmark-item {
display: flex;
justify-content: space-between;
align-items: center;
margin: 10px 0;
padding: 10px;
border: 1px solid #ddd;
border-radius: 5px;
background-color: #fafafa;
background-color: var(--bg-color);
color: var(--text-color);
}
.bookmark-item a {
text-decoration: none;
color: var(--link-color);
}
.bookmark-item button {
padding: 5px 10px;
font-size: 14px;
background-color: var(--delete-btn-bg-color);
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
}
.bookmark-item button:hover {
background-color: var(--delete-btn-hover-color);
}
.controls {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
</style>
</head>
<body data-theme="light">
<div class="container">
<h1>ブックマークサイト</h1>
<div class="controls">
<input type="text" id="search-bar" placeholder="ブックマークを検索" oninput="filterBookmarks()">
<select id="category-filter" onchange="filterByCategory()">
<option value="all">すべてのカテゴリー</option>
</select>
<button onclick="toggleTheme()">ダークモード切り替え</button>
</div>
<div class="bookmark-form">
<input type="text" id="bookmark-title" placeholder="タイトルを入力してください" required>
<input type="url" id="bookmark-url" placeholder="URLを入力してください" required>
<input type="text" id="bookmark-category" placeholder="カテゴリーを入力してください">
<button onclick="addBookmark()">ブックマークを追加</button>
</div>
<ul id="bookmark-list" class="bookmark-list"></ul>
</div>
<script>
document.addEventListener('DOMContentLoaded', loadBookmarks);
function loadBookmarks() {
const bookmarks = JSON.parse(localStorage.getItem('bookmarks')) || [];
const categories = new Set();
bookmarks.forEach(bookmark => {
renderBookmark(bookmark);
categories.add(bookmark.category);
});
updateCategoryFilter(Array.from(categories));
}
function addBookmark() {
const titleInput = document.getElementById('bookmark-title');
const urlInput = document.getElementById('bookmark-url');
const categoryInput = document.getElementById('bookmark-category');
const title = titleInput.value.trim();
const url = urlInput.value.trim();
const category = categoryInput.value.trim();
if (title === '' || url === '') {
alert('タイトルとURLを入力してください。');
return;
}
const bookmark = { title, url, category };
saveBookmark(bookmark);
renderBookmark(bookmark);
titleInput.value = '';
urlInput.value = '';
categoryInput.value = '';
updateCategoryFilter([category]);
}
function saveBookmark(bookmark) {
const bookmarks = JSON.parse(localStorage.getItem('bookmarks')) || [];
bookmarks.push(bookmark);
localStorage.setItem('bookmarks', JSON.stringify(bookmarks));
}
function renderBookmark(bookmark) {
const bookmarkList = document.getElementById('bookmark-list');
const listItem = document.createElement('li');
listItem.className = 'bookmark-item';
listItem.innerHTML = `
<span>${bookmark.title} (${bookmark.category})</span>
<div>
<a href="${bookmark.url}" target="_blank">訪問</a>
<button onclick="editBookmark('${bookmark.url}')">編集</button>
<button onclick="deleteBookmark('${bookmark.url}')">削除</button>
</div>
`;
bookmarkList.appendChild(listItem);
}
function deleteBookmark(url) {
let bookmarks = JSON.parse(localStorage.getItem('bookmarks')) || [];
bookmarks = bookmarks.filter(bookmark => bookmark.url !== url);
localStorage.setItem('bookmarks', JSON.stringify(bookmarks));
refreshBookmarkList();
}
function editBookmark(url) {
let bookmarks = JSON.parse(localStorage.getItem('bookmarks')) || [];
const bookmark = bookmarks.find(bookmark => bookmark.url === url);
if (bookmark) {
document.getElementById('bookmark-title').value = bookmark.title;
document.getElementById('bookmark-url').value = bookmark.url;
document.getElementById('bookmark-category').value = bookmark.category;
deleteBookmark(url); // 編集のために一旦削除
}
}
function refreshBookmarkList() {
const bookmarkList = document.getElementById('bookmark-list');
bookmarkList.innerHTML = '';
loadBookmarks();
}
function filterBookmarks() {
const query = document.getElementById('search-bar').value.toLowerCase();
const bookmarkItems = document.querySelectorAll('.bookmark-item');
bookmarkItems.forEach(item => {
const title = item.querySelector('span').innerText.toLowerCase();
item.style.display = title.includes(query) ? 'flex' : 'none';
});
}
function filterByCategory() {
const category = document.getElementById('category-filter').value;
const bookmarkItems = document.querySelectorAll('.bookmark-item');
bookmarkItems.forEach(item => {
const itemCategory = item.querySelector('span').innerText.split(' (')[1].slice(0, -1);
item.style.display = (category === 'all' || itemCategory === category) ? 'flex' : 'none';
});
}
function updateCategoryFilter(categories) {
const filter = document.getElementById('category-filter');
categories.forEach(category => {
if (![...filter.options].some(option => option.value === category)) {
const option = document.createElement('option');
option.value = category;
option.textContent = category;
filter.appendChild(option);
}
});
}
function toggleTheme() {
const body = document.body;
const currentTheme = body.getAttribute('data-theme');
const newTheme = currentTheme === 'light' ? 'dark' : 'light';
body.setAttribute('data-theme', newTheme);
}
</script>
</body>
</html>