table
タグで書かれた一覧表に、ソートをかけるライブラリをよく見かけます。
が、汎用的にソート機能を追加したいときに使えるスニペットを作ってみました。
応用すれば、カードコンポーネントの並び替えや、リストの並び替え等々色々使えて便利です。
是非、参考にしてみてください。
.addEventListener()
.addEventListener()
の change
イベントは、ユーザーによる要素の値の変更が確定したときに発行されます。
selectElement.addEventListener('change', (event) => {
// ここに処理内容
});
<input>
, <select>
, <textarea>
タグで発火するイベントで、この記事では .addEventListener()
メソッドの引数として change
で処理を記述しています。
ラジオボタンクリックで要素のソートサンプル
早速サンプルです。
以下に、リストに「日付け」「数字」の2つを持つ文字列が5つ並び、その上部に「日付け」「数字」の昇順・降順で並び替えのできるラジオボタンが4つ並びます。
このラジオボタンをクリックすると、リストの中の日付け・数字を基に指定順のソートがかかります。
-
リスト1 3552022年10月10日
-
リスト2 2802022年12月08日
-
リスト3 402021年04月02日
-
リスト4 3202020年09月01日
-
リスト5 10202019年01月28日
このように、フロント側でソートをかけるスニペットをコードもあわせて解説していきます。
実装の手順と方法
コードの解説の前に、この記事のサンプルUIの実装手順と方法について解説していきます。
まずは、以下のHTMLタグを任意の場所に記述します。
設置したい場所に配置しましょう。
<form name="formSort" id="form">
<label><input class="inputRadio" type="radio" name="formSortbtn" value="newDate" checked>日付けが新しい順
</label>
<label><input class="inputRadio" type="radio" name="formSortbtn" value="OldDate">日付けが古い順</label>
<label><input class="inputRadio" type="radio" name="formSortbtn" value="bigScore">数字が大きい順</label>
<label><input class="inputRadio" type="radio" name="formSortbtn" value="smallScore">数字が小さい順</label>
</form>
<!-- ここからリスト -->
<ul id="sampleList">
<li>
<p>リスト1 <span class="score">355</span><span class="date">2022年10月10日</span></p>
</p>
</li>
<li>
<p>リスト2 <span class="score">280</span><span class="date">2022年12月08日</span></p>
</p>
</li>
<li>
<p>リスト3 <span class="score">40</span><span class="date">2021年04月02日</span></p>
</p>
</li>
<li>
<p>リスト4 <span class="score">320</span><span class="date">2020年09月01日</span></p>
</p>
</li>
<li>
<p>リスト5 <span class="score">1020</span><span class="date">2019年01月28日</span></p>
</p>
</li>
</ul>
<!-- ここまでリスト -->
次に、JavaScriptでSwiperのオプションを記述します。
コードは <body>〜</body>
で、</body>
の閉じタグ(クロージングタグ)の前に記述しましょう。
// フォームを取得
const selectElement = document.querySelector('#form');
// フォーム内に変更が加わった時の処理
selectElement.addEventListener('change', (event) => {
console.log('選択が変更されました');
// フォーム内のラジオボタンを取得。checked でチェックがついた時。
var rcheck1 = document.formSort.formSortbtn[0].checked;
var rcheck2 = document.formSort.formSortbtn[1].checked;
var rcheck3 = document.formSort.formSortbtn[2].checked;
var rcheck4 = document.formSort.formSortbtn[3].checked;
// チェックがついた時の条件分岐
// 1
if (rcheck1) { //日付け新しい
console.log('日付けが新しい順');
// リストの取得
var container = document.querySelector('#sampleList');
[].slice.call(container.querySelectorAll('li'))
.map(function(v){
// .date の要素を取得する
var value = v.querySelector('.date').innerHTML.replace(/<.+>/,'').replace(/\D/g,'') - 0;
return { dom: v, value: value };
})
// sortをかける
.sort(function(a,b){ return b.value - a.value; })
.forEach(function(v){ container.appendChild(v.dom); });
} else if(rcheck2) { //日付けが古い順
console.log('日付けが古い順');
var container = document.querySelector('#sampleList');
[].slice.call(container.querySelectorAll('li'))
.map(function(v){
var value = v.querySelector('.date').innerHTML.replace(/<.+>/,'').replace(/\D/g,'') - 0;
return { dom: v, value: value };
})
.sort(function(a,b){ return a.value - b.value; })
.forEach(function(v){ container.appendChild(v.dom); });
} else if(rcheck3) { //falseの場合
console.log('数字が大きい順');
var container = document.querySelector('#sampleList');
[].slice.call(container.querySelectorAll('li'))
.map(function(v){
var value = v.querySelector('.score').innerHTML.replace(/<.+>/,'').replace(/\D/g,'') - 0;
return { dom: v, value: value };
})
.sort(function(a,b){ return b.value - a.value; })
.forEach(function(v){ container.appendChild(v.dom); });
} else { //falseの場合
console.log('数字が小さい順');
var container = document.querySelector('#sampleList');
[].slice.call(container.querySelectorAll('li'))
.map(function(v){
var value = v.querySelector('.score').innerHTML.replace(/<.+>/,'').replace(/\D/g,'') - 0;
return { dom: v, value: value };
})
.sort(function(a,b){ return a.value - b.value; })
.forEach(function(v){ container.appendChild(v.dom); });
}
});
最後にCSSを記述して、見た目を整えれば完成です。
form#form {
display: flex;
justify-content: center;
gap: 5px 25px;
padding: 10px 10px 9px;
font-size: 0.9rem;
border-radius: 3px;
background: #FFF;
filter: drop-shadow(0px 1px 2px #eee);
position: relative;
margin-bottom: 25px;
flex-wrap: wrap;
}
form#form:after {
content: "";
position: absolute;
top: 100%;
left: 50%;
margin-left: -12px;
border: 12px solid transparent;
border-top: 12px solid #FFF;
}
form#form label {
display: inline-flex;
justify-content: flex-start;
align-items: center;
gap: 5px;
cursor: pointer;
}
form#form label input {
display: inline-flex;
justify-content: flex-start;
transform: scale(1.3) translateY(-1px);
cursor: pointer;
}
ul#sampleList {
list-style: none;
padding: 20px 25px;
background: #FFF;
border: none;
display: flex;
flex-direction: column;
gap: 15px;
margin: 0;
}
ul#sampleList li {
margin: 0;
padding: 0;
}
ul#sampleList li p {
margin: 0;
display: flex;
justify-content: flex-start;
gap: 10px;
flex-wrap: wrap;
align-items: center;
}
ul#sampleList li p span {
background: #f0f0f0;
padding: 5px 14px;
line-height: 1;
font-size: 0.9rem;
position: relative;
color: #707070;
border-radius: 3px;
}
span.score:before {
position: relative;
content: "\f51e";
font-family: "Font Awesome 5 Free" !important;
font-weight: 900;
opacity: 0.7;
margin-right: 5px;
font-size: 0.7rem;
}
span.date:before {
position: relative;
content: "\f073";
font-family: "Font Awesome 5 Free" !important;
font-weight: 900;
opacity: 0.7;
margin-right: 5px;
font-size: 0.7rem;
vertical-align: 1px;
}
ざっくりとしたコードの解説
コードは、HTML・JavaScript・CSSの3種類です。
HTMLは「ソートのトリガーになるラジオボタン」と「ソート対象のリスト」の2つ。そして、JavaScriptは「ソート」の処理を行う記述です。そして、CSSが「レイアウトと見た目を整える」です。
この3つのコードについて、順に解説していきます。
HTML
HTMLは、ソートのトリガーになるフォームと、並び替えの対象になるリストでそれぞれ作ります。
フォームは、「form」タグにはid名を持たせた形で作り、その中に label
input
タグを入れていきます。
<form name="formSort" id="form">
<label><input class="inputRadio" type="radio" name="formSortbtn" value="newDate" checked>日付けが新しい順
</label>
<label><input class="inputRadio" type="radio" name="formSortbtn" value="OldDate">日付けが古い順</label>
<label><input class="inputRadio" type="radio" name="formSortbtn" value="bigScore">数字が大きい順</label>
<label><input class="inputRadio" type="radio" name="formSortbtn" value="smallScore">数字が小さい順</label>
</form>
<!-- ここからリスト -->
<ul id="sampleList">
<li>
<p>リスト1 <span class="score">355</span><span class="date">2022年10月10日</span></p>
</p>
</li>
<li>
<p>リスト2 <span class="score">280</span><span class="date">2022年12月08日</span></p>
</p>
</li>
<li>
<p>リスト3 <span class="score">40</span><span class="date">2021年04月02日</span></p>
</p>
</li>
<li>
<p>リスト4 <span class="score">320</span><span class="date">2020年09月01日</span></p>
</p>
</li>
<li>
<p>リスト5 <span class="score">1020</span><span class="date">2019年01月28日</span></p>
</p>
</li>
</ul>
<!-- ここまでリスト -->
そして、ソートの対象にするリストは ul
タグでブロックを作っていきます。
この時、中の li
タグに p
タグと span
タグを入れていきますが、後述のソート機能を動かす為 span
タグには任意のclass名を付けます。
JavaScript
JavaScriptは、大きく分けて「フォーム内容に変更があった時」「ラジオボタンにチェックが入った時」「チェックが入った時のソート」の3つの記述内容です。
// フォームを取得
const selectElement = document.querySelector('#form');
// フォーム内に変更が加わった時の処理
selectElement.addEventListener('change', (event) => {
console.log('選択が変更されました');
// フォーム内のラジオボタンを取得。checked でチェックがついた時。
var rcheck1 = document.formSort.formSortbtn[0].checked;
var rcheck2 = document.formSort.formSortbtn[1].checked;
var rcheck3 = document.formSort.formSortbtn[2].checked;
var rcheck4 = document.formSort.formSortbtn[3].checked;
// チェックがついた時の条件分岐
// 1
if (rcheck1) { //日付け新しい
console.log('日付けが新しい順');
// リストの取得
var container = document.querySelector('#sampleList');
[].slice.call(container.querySelectorAll('li'))
.map(function(v){
// .date の要素を取得する
var value = v.querySelector('.date').innerHTML.replace(/<.+>/,'').replace(/\D/g,'') - 0;
return { dom: v, value: value };
})
// sortをかける
.sort(function(a,b){ return b.value - a.value; })
.forEach(function(v){ container.appendChild(v.dom); });
} else if(rcheck2) { //日付けが古い順
console.log('日付けが古い順');
var container = document.querySelector('#sampleList');
[].slice.call(container.querySelectorAll('li'))
.map(function(v){
var value = v.querySelector('.date').innerHTML.replace(/<.+>/,'').replace(/\D/g,'') - 0;
return { dom: v, value: value };
})
.sort(function(a,b){ return a.value - b.value; })
.forEach(function(v){ container.appendChild(v.dom); });
} else if(rcheck3) { //falseの場合
console.log('数字が大きい順');
var container = document.querySelector('#sampleList');
[].slice.call(container.querySelectorAll('li'))
.map(function(v){
var value = v.querySelector('.score').innerHTML.replace(/<.+>/,'').replace(/\D/g,'') - 0;
return { dom: v, value: value };
})
.sort(function(a,b){ return b.value - a.value; })
.forEach(function(v){ container.appendChild(v.dom); });
} else { //falseの場合
console.log('数字が小さい順');
var container = document.querySelector('#sampleList');
[].slice.call(container.querySelectorAll('li'))
.map(function(v){
var value = v.querySelector('.score').innerHTML.replace(/<.+>/,'').replace(/\D/g,'') - 0;
return { dom: v, value: value };
})
.sort(function(a,b){ return a.value - b.value; })
.forEach(function(v){ container.appendChild(v.dom); });
}
});
コード量は比較的多めです。
コード内容や、詳細の処理についてはコメントアウトで記述していますが、1個1個見ていくと処理内容がわかりやすいと思うので、カスタマイズするときはコメントとあわせて使うようにしてください。
if構文で処理を分けているので、ソートルールも追加・削除しやすいと思います。
CSS
CSSは、ラジオボタン周りの form
input
label
と、レイアウトを整える記述がメインです。
form#form {
display: flex;
justify-content: center;
gap: 5px 25px;
padding: 10px 10px 9px;
font-size: 0.9rem;
border-radius: 3px;
background: #FFF;
filter: drop-shadow(0px 1px 2px #eee);
position: relative;
margin-bottom: 25px;
flex-wrap: wrap;
}
form#form:after {
content: "";
position: absolute;
top: 100%;
left: 50%;
margin-left: -12px;
border: 12px solid transparent;
border-top: 12px solid #FFF;
}
form#form label {
display: inline-flex;
justify-content: flex-start;
align-items: center;
gap: 5px;
cursor: pointer;
}
form#form label input {
display: inline-flex;
justify-content: flex-start;
transform: scale(1.3) translateY(-1px);
cursor: pointer;
}
ul#sampleList {
list-style: none;
padding: 20px 25px;
background: #FFF;
border: none;
display: flex;
flex-direction: column;
gap: 15px;
margin: 0;
}
ul#sampleList li {
margin: 0;
padding: 0;
}
ul#sampleList li p {
margin: 0;
display: flex;
justify-content: flex-start;
gap: 10px;
flex-wrap: wrap;
align-items: center;
}
ul#sampleList li p span {
background: #f0f0f0;
padding: 5px 14px;
line-height: 1;
font-size: 0.9rem;
position: relative;
color: #707070;
border-radius: 3px;
}
span.score:before {
position: relative;
content: "\f51e";
font-family: "Font Awesome 5 Free" !important;
font-weight: 900;
opacity: 0.7;
margin-right: 5px;
font-size: 0.7rem;
}
span.date:before {
position: relative;
content: "\f073";
font-family: "Font Awesome 5 Free" !important;
font-weight: 900;
opacity: 0.7;
margin-right: 5px;
font-size: 0.7rem;
vertical-align: 1px;
}
一部のラベルに擬似要素にFontAwesomeを使っていますが、好みに応じて削除したり書き換えて使うようにしてください。
さいごに
コード量は多めの内容でしたが、HTMLの要素が多めでも気軽にソートをかけられるので、是非使ってみてください。