junkerstock
 todo-test1 

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>Mobile Ready TODO List</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Sortable/1.15.0/Sortable.min.js"></script>
<style>
/* --- CSS: スマホ向け調整済み --- */
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
background-color: #f0f2f5;
display: flex;
justify-content: center;
padding: 20px 10px; /* スマホ用に余白を調整 */
margin: 0;
/* iOSでのタップ時のハイライトを消す */
-webkit-tap-highlight-color: transparent;
}

.container {
width: 100%;
max-width: 500px; /* スマホでは画面いっぱい、PCでは幅制限 */
background: #fff;
padding: 20px;
border-radius: 12px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}

h2 {
text-align: center;
color: #333;
margin-top: 0;
font-size: 1.5rem;
}

.input-group {
display: flex;
margin-bottom: 20px;
box-shadow: 0 2px 5px rgba(0,0,0,0.05);
border-radius: 8px;
overflow: hidden;
}

#task-input {
flex-grow: 1;
padding: 12px 15px;
border: 1px solid #ddd;
border-right: none;
outline: none;
/* ★ここが重要: 16px以上にするとスマホでズームされない */
font-size: 16px;
border-radius: 8px 0 0 8px;
}

#add-btn {
padding: 0 20px;
background-color: #007bff;
color: white;
border: none;
cursor: pointer;
font-weight: bold;
font-size: 16px;
border-radius: 0 8px 8px 0;
/* タップしやすくする */
min-width: 60px;
}

#add-btn:active {
background-color: #0056b3;
}

.todo-list {
list-style: none;
padding: 0;
margin: 0;
min-height: 50px; /* リストが空でもドラッグエリアを確保 */
}

.todo-item {
background-color: #fff;
border-bottom: 1px solid #eee;
padding: 15px 10px;
display: flex;
justify-content: space-between;
align-items: center;
/* スマホで長押しメニューが出ないようにする */
user-select: none;
touch-action: pan-y; /* 縦スクロールは許可、横はドラッグ判定 */
}

/* 最後の線の処理 */
.todo-item:last-child {
border-bottom: none;
}

.todo-text {
flex-grow: 1;
font-size: 16px;
padding-right: 10px;
word-break: break-all;
cursor: grab; /* 掴めるアイコン */
}

/* ハンドルアイコン(視覚的なガイド) */
.handle {
color: #ccc;
margin-right: 10px;
cursor: grab;
font-size: 20px;
}

.delete-btn {
background-color: #ff4d4d;
color: white;
border: none;
padding: 8px 12px;
border-radius: 6px;
cursor: pointer;
font-size: 14px;
margin-left: 5px;
flex-shrink: 0; /* ボタンが潰れないようにする */
}

/* ドラッグ中のスタイル(SortableJS用) */
.sortable-ghost {
opacity: 0.4;
background-color: #e3f2fd;
}

.sortable-drag {
background: #fff;
box-shadow: 0 5px 15px rgba(0,0,0,0.15);
opacity: 1;
}
</style>
</head>
<body>

<div class="container">
<h2>My Tasks</h2>
<div class="input-group">
<input type="text" id="task-input" placeholder="タスクを入力..." autocomplete="off">
<button id="add-btn">追加</button>
</div>
<ul id="todo-list" class="todo-list">
</ul>
</div>

<script>
const input = document.getElementById('task-input');
const addBtn = document.getElementById('add-btn');
const list = document.getElementById('todo-list');

// ★重要: SortableJSの初期化(これだけでスマホ対応ドラッグ&ドロップが完了)
new Sortable(list, {
animation: 150, // 移動時のアニメーション速度(ms)
ghostClass: 'sortable-ghost', // ドロップ予定地のスタイル
dragClass: 'sortable-drag', // ドラッグ中の要素スタイル
handle: '.todo-item', // 行全体でドラッグ可能にする
delay: 100, // スマホでの誤操作防止(少し長押しでドラッグ開始)※好みで0でもOK
delayOnTouchOnly: true // PCでは即座にドラッグ、スマホだけ長押し判定
});

// 初期タスク
addTodo('長押しで移動できます');
addTodo('ズームされず入力できます');
addTodo('買い物に行く');

// 追加ボタン
addBtn.addEventListener('click', () => {
const text = input.value.trim();
if (text) {
addTodo(text);
input.value = '';
input.focus(); // 続けて入力しやすくする
}
});

// Enterキー対応
input.addEventListener('keypress', (e) => {
if (e.key === 'Enter') {
addBtn.click();
}
});

// タスク追加関数
function addTodo(text) {
const li = document.createElement('li');
li.classList.add('todo-item');

// タスクの中身 (≡ はドラッグ用のハンドルアイコン代わり)
li.innerHTML = `
<span class="handle">≡</span>
<span class="todo-text">${text}</span>
<button class="delete-btn">削除</button>
`;

// 削除機能
li.querySelector('.delete-btn').addEventListener('click', (e) => {
// 削除ボタンを押したときにドラッグが暴発しないように伝播を止める
e.stopPropagation();

// アニメーションっぽく消す
li.style.transform = 'translateX(100%)';
li.style.transition = '0.3s';
setTimeout(() => {
li.remove();
}, 300);
});

list.appendChild(li);

// 最新のタスクが見えるようにスクロール
li.scrollIntoView({ behavior: 'smooth', block: 'end' });
}
</script>

</body>
</html>


使用変数

addBtn
addTodo -------( Function )
autocomplete
charset
class
content
id
innerHTML
input
key
lang
li
list
name
placeholder
scalable
scale
src
text
transform
transition
type
value
width