⛳
jsで簡易的なソート機能を実装。
概要
html直書きのデータを参照して、ソートしてくれる機能を実装しました。
<div class="item">
<h3>アンドロイドタブレット</h3>←これは何でもよい
<div class="price">45000</div>
<div class="spec">150000</div>
</div>
これが基本単位。
jsのコードを変更すればパラメータは増やせるので、適宜変更してください。
今回は、データベースを使わずに、だれでもコンテンツのソートができるものを作りました。
速度等は一切考慮していません。
データは基本的に数値型。
円表記はしないでください。
表示が煩わしい場合は、
<div class="item">
<div class="price" style = "display:none;">45000</div>
<div class="spec" style = "display:none;">150000</div>
</div>
動的に読み込むようなものは考慮していません。
動的にサーバーからデータを取得できる方は
そもそもソート機能を実装できるからです。
今回の対象は、ホームページを運営しているが、jsはあまり触れたことがない方用です。
テストがしやすいように単一ファイルで張り付けておきます
<!DOCTYPE html>
<html>
<head>
<style>
.item { border: 1px solid #ccc; padding: 10px; margin: 5px; }
.controls { margin: 20px 0; padding: 10px; background: #f5f5f5; }
.filter-group { margin-right: 20px; }
</style>
</head>
<!--
動作要件
HTMLに事前にitem要素が存在する必要があります
各item要素は正しいclass構成(priceとspec)を持っている必要があります
sort_content要素がページ内に存在する必要があります
拡張する場合のヒント
動的にitem要素を追加する場合は、追加後にinitializeData()を再実行
データ更新時はoriginalData配列を直接更新
サーバーサイドからのデータ取得が必要な場合は、fetch後にDOM要素を生成してから初期化処理を実行
-->
<body>
<!-- コントロールパネル -->
<div class="controls">
<div class="filter-group">
ソートキー:
<select id="sortKey">
<option value="price">価格</option>
<option value="spec">スペック</option>
</select>
</div>
<div class="filter-group">
ソート順:
<select id="sortOrder">
<option value="asc">昇順</option>
<option value="desc">降順</option>
</select>
</div>
<div class="filter-group">
価格範囲:
<input type="number" id="minPrice" placeholder="最小価格">
~
<input type="number" id="maxPrice" placeholder="最大価格">
</div>
<div class="filter-group">
スペック範囲:
<input type="number" id="minSpec" placeholder="最小スペック">
~
<input type="number" id="maxSpec" placeholder="最大スペック">
</div>
<button onclick="updateDisplay()">適用</button>
</div>
<!-- データコンテナのHTML例 -->
<div id="sort_content">
<div class="item">
<div class="price">30000</div>
<div class="spec">100000</div>
</div>
<div class="item">
<div class="price">45000</div>
<div class="spec">150000</div>
</div>
<!-- その他のitem要素 -->
</div>
<!-- データ表示領域 -->
<div id="container"></div>
<script>
// 初期データ保持用変数
let originalData = [];
// データ初期化(sort_contentから取得)
const initializeData = () => {
const container = document.getElementById('sort_content');
originalData = [];
// 既存のitem要素を取得
const items = container.getElementsByClassName('item');
Array.from(items).forEach(item => {
// 元データを保持(DOM要素と数値データを紐付け)
originalData.push({
element: item.cloneNode(true), // クローンを保持
price: parseInt(item.querySelector('.price').textContent),
spec: parseInt(item.querySelector('.spec').textContent)
});
});
// 初期表示用にコンテナをクリア
container.innerHTML = '';
};
// データ取得関数
const getItemsData = () => {
return originalData.map(data => ({...data})); // ディープコピー
};
// 表示更新
const updateDisplay = () => {
const container = document.getElementById('sort_content');
const sortKey = document.getElementById('sortKey').value;
const sortOrder = document.getElementById('sortOrder').value;
let data = getItemsData();
data = filterItems(data);
data = sortItems(data, sortKey, sortOrder);
container.innerHTML = '';
data.forEach(item => {
container.appendChild(item.element.cloneNode(true));
});
};
// ソート処理
const sortItems = (data, key, order) => {
return data.sort((a, b) => {
const modifier = order === 'asc' ? 1 : -1;
return (a[key] - b[key]) * modifier;
});
};
/*
// フィルタリング処理
const filterItems = (data) => {
const minPrice = parseInt(document.getElementById('minPrice').value) || -Infinity;
const maxPrice = parseInt(document.getElementById('maxPrice').value) || Infinity;
const minSpec = parseInt(document.getElementById('minSpec').value) || -Infinity;
const maxSpec = parseInt(document.getElementById('maxSpec').value) || Infinity;
return data.filter(item =>
item.price >= minPrice &&
item.price <= maxPrice &&
item.spec >= minSpec &&
item.spec <= maxSpec
);
};
*/
//上の方法だとうまくいかないので以下にしました
// フィルタリング処理(改修版)
const filterItems = (data) => {
// 価格範囲の処理
const minPriceInput = document.getElementById('minPrice');
const maxPriceInput = document.getElementById('maxPrice');
const minPrice = minPriceInput.value !== ''
? parseInt(minPriceInput.value)
: 0; // 未入力時は0
const maxPrice = maxPriceInput.value !== ''
? parseInt(maxPriceInput.value)
: Number.MAX_SAFE_INTEGER; // 未入力時は最大値
// スペック範囲の処理
const minSpecInput = document.getElementById('minSpec');
const maxSpecInput = document.getElementById('maxSpec');
const minSpec = minSpecInput.value !== ''
? parseInt(minSpecInput.value)
: 0; // 未入力時は0
const maxSpec = maxSpecInput.value !== ''
? parseInt(maxSpecInput.value)
: Number.MAX_SAFE_INTEGER; // 未入力時は最大値
return data.filter(item =>
item.price >= minPrice &&
item.price <= maxPrice &&
item.spec >= minSpec &&
item.spec <= maxSpec
);
};
// 初期化処理
window.addEventListener('DOMContentLoaded', () => {
initializeData();
updateDisplay();
});
</script>
</body>
</html>
Discussion