##経緯
やんごとなき理由でhtml側をいじれなかったため、
jsでどうにかこうにか入れ替える必要がありました。
以下奮闘記です。
もっといい書き方があればコメント下さい。泣いて喜びます。
##今回の要件
- お店の開店時間が早い順にソートしたい
- 開店時間が同じ場合でも、閉店時間による並べ替えはしない
- 時間は24時間表記、30分刻みとする
- 営業時間は必ず
HH:mm ~ HH:mm
のフォーマットで表記される - すべての店の営業時間は10:00 ~ 5:00の範囲内に収まる(5時オープンの店はない)
##デモ
デモはこちら。
開店時間を変更しても、並び替わってくれます。
##HTML
<ul class="shop_lists">
<li>
<div class="shop">HOGE食堂</div>
<div class="time">12:00 ~ 18:00</div>
</li>
<li>
<div class="shop">FUGA KITCHEN</div>
<div class="time">10:00 ~ 20:00</div>
</li>
<li>
<div class="shop">BAR NULL</div>
<div class="time">1:00 ~ 4:00</div>
</li>
</ul>
##javascript
$('.shop_lists').html(
$('.shop_lists > li').sort(function(a,b){
var str1 = $(a).find('.time').html();
var str2 = $(b).find('.time').html();
var num1 = str1.substr( 0, 4 ).split(':');
var num2 = str2.substr( 0, 4 ).split(':');
if(num1[0] < 5){
num1[0] = Number(num1[0]) + 24;
num1[0] += Number(num1[1]) / 100;
}
if(num2[0] < 5){
num2[0] = Number(num2[0]) + 24;
num2[0] += Number(num2[1]) / 100;
}
return num1[0] - num2[0];
}));
##生意気にも解説
###リストの入れ替え
$('.shop_lists > li').sort(function(a,b){
sort
メソッドで数値を複数回比較、比較した値を基に、
liタグの並べ替えを行います。
比較方法については次から。
###基準となる数値を含む文字列を抽出
var str1 = $(a).find('.time').html();
var str2 = $(b).find('.time').html();
a
とb
それぞれに、リストがセットされて行くので、
その中から、time
クラスを持つブロックを指定し、
htmlメソッドで中身(今回だと12:00 ~ 18:00
)を抽出します。
ただ、これだと~
と閉店時間が含まれてしまうため、
次に開店時間のみ抽出していきます。
###数値の抽出と比較の下準備
var num1 = str1.substr( 0, 4 ).split(':');
まず、セットされた文字列から先頭の4文字を指定substr( 0, 4 )
します。
12:00 ~ 18:00
だと12:0
になりますね。
※今回は時間が30分刻みで、1分単位での比較はしなくて良いので切り捨てています。
次に、文字列を:
を基準に、分割し配列化します。
上の例だと、num1 = ['12', '0']
となります。
では、この配列の値を基準に比較する処理に入ります。
###比較方法
return num1[0] - num2[0];
順番が前後しますが、結論から言うと、
配列の最初の値num[0]
を比較します。
この比較結果を基にリストを並べ替えていくわけですね。(完全に理解)
####問題点
ただこれだけだと、以下の問題が発生してしまいます。
- リスト分単位での比較が出来ない
- 0時以降オープンのお店が、10時オープンのお店より先に表示されてしまう
そのため今回は、
- 分単位部分の
num[1]
を少数点以下の数値に変換し、num[0]
に加算。 - 0時〜5時の場合は、
num[0]
に24を足す(24時〜28時に変換)
これらの処理を挟むことにしました。
###問題点を解決する処理
if(num1[0] < 6){
num1[0] = Number(num1[0]) + 24;
num1[0] += Number(num1[1]) / 100;
//結果(1時半オープンの場合): num1[0] = 25.3
}
この部分ですね。
暗黙の型変換でそのまま24を足したり100で割ることもできるみたいですが、
丁寧に書きましょうということで、Numberオブジェクトで型変換の後に計算。
これで、先程の問題は解決します。
あとは先程の比較式に値が渡るので、比較の後、並べ替え完了です!!!
##思うところ
aとbで同じ処理してるので、うまいことまとめられないかなーというのが正直な所。
ループ回したりしてカッチョイイコードを書きたいものの、
正直わかりやすいし2回くらいならいっか()という惰性です。
あと、時間フォーマットの変更に強くないので、
その場しのぎ感は否めないかと。
自分のコードを呪う未来が見えるような、見えないような....。
間違い等あれば、ご指摘下さい。