馬拉松需要提前好幾個月前報名,熱門賽事報名又常上演秒殺戲碼,因此全盤掌握未來半年賽事資訊,妥善規劃「檔期」、留意報名時間是愛馬士(愛跑馬人士)的必備功課。我個人則偏愛運動筆記的賽事列表,除了資訊完整,程式部分採用jQuery/AJAX,介面富有濃厚的HTML5風格,甚至還用了Font Awesome呢!(謎之聲:這些跟馬拉松比賽是有什麼關係啦?)
唯一美中不足-運動筆記的賽事網頁沒有距離篩選功能,台灣這幾年路跑賽事多如牛毛,查詢結果項目超過200筆,網頁本身提供地點、類型、年份篩選,卻沒有鎖定特定距離(全馬、半馬)的功能。對我這種鎖定全馬拼業績的人,得在一堆比賽挑出全馬,有點小麻煩。
會寫網頁有一項額外好處:遇到網頁不如己意,動手改到自己開心!
我寫了一個小外掛,為運動筆記賽事網頁偷偷加上自製距離篩選器,篩選器可掃瞄所有賽事加以分類,分成5K、5K+(5K以上,21K以下)、半馬、超半馬、全馬及超馬,預設為全部顯示,點選距離項目右側的小叉叉可排除該分類。如下圖所示,清單可以只顯示有全馬項目的比賽:
如果想使用這個篩選功能,Chrome瀏覽器需先安裝Tampermonkey(Firefox則要安裝Greasemonkey),接著可連Grease Fork點選「安裝腳本」:
以Tampermonkey為例,按下「安裝腳本」後,會進入程式碼檢視頁面,請點選「安裝」:
之後,重新進入運動筆記賽事頁面,Tampermonkey圖示會顯示紅字的1,點選圖示展開選單可見「運動筆記賽事清單路跑距離篩選」,若想停用可點選前方的綠色數字鈕。
這時可以看一下網頁,年份篩選器的下方會默默多出距離選項,Enjoy It!
外掛畢竟還是奇技淫巧,運動筆記直接內建距離篩選功能才是最完美的解決方案。附上程式碼,並將它設成CC0(公眾領域貢獻宣告)授權,對於參考、引用、改寫(且不需加註原作者)均不設限,希望能有一丁點貢獻。
// ==UserScript== // @name 運動筆記賽事清單路跑距離篩選 // @namespace http://blog.darkthread.net/ // @version 0.9.2 // @description 為運動筆記之賽事清單加入路跑距離篩選器 by Jeffrey Lee, 黑暗執行緒 // @match http://tw.running.biji.co/index.php?q=competition* // @license http://creativecommons.tw/cc0 // ==/UserScript== //依長度不同區分為六大類 var distCatgs = { "5K": "5k", "5K+": "5k-plus", "半馬": "half-ma", "超半馬": "ultra-half-ma", "全馬": "std-ma", "超馬": "ultra-ma" }; function scanEvents() { //若先前已掃瞄過,略過不處理 if ($(".com_detail_info:first").hasClass("scan")) return; //掃瞄所有賽事,依其距離分類,以class標註於資料列元素 //場數統計表 var stats = {}; $(".com_detail_info .competition_event .event_item").each(function() { var match = /[0-9.]+K/.exec(this.innerText); if (!match) return; var dist = match[0]; var km = parseInt(dist.replace("K", "")); // 分類成 5K, 5K+, 半馬, 超半馬, 全馬, 超馬 var catg = "5K"; if (km > 5 && km <21) catg = "5K+"; elseif (km == 21) catg = "半馬"; elseif (km > 21 && km < 42) catg = "超半馬"; elseif (km == 42) catg = "全馬"; elseif (km > 42) catg = "超馬"; // 在資料列元素上以class標示 $(this).closest(".com_detail_info").addClass(distCatgs[catg]); if (stats.hasOwnProperty(catg)) stats[catg]++; else stats[catg] = 1; }); console.log("Scanned"); //更新統計數於篩選鈕後方 var $fltrBar = $("#distance_filter"); $.each(Object.keys(distCatgs), function(i, c) { $fltrBar.find("." + distCatgs[c] + " .counter").text(stats[c]); }); //在第一筆賽事做記號註記已經掃瞄 $(".com_detail_info:first").addClass("scanned"); } // 加入篩選器 $("#distance_filter").remove(); //若已存在先移除之 var h = []; $.each(Object.keys(distCatgs), function(i, d) { h.push( '<div class="float_select ' + distCatgs[d] + '" data-catg="' + distCatgs[d] + '">' + '<div class="filter_choose_item com_type filter_select_item">' + d + ' <span style="font-size:80%">(<span class="counter"></span>)</span>' + '</div>' + '<div class="drop_choose fa fa-remove" style="display:block"></div>' + '</div>'); }); $("#menu_choose_bar .filter_item:last").before( '<div class="filter_item" id="distance_filter">' + '<div class="filter_type">距離</div>' + '<div class="filter_value">' + h.join() + '</div></div>'); var $filterBar = $("#distance_filter"); $filterBar.on("click", ".filter_choose_item", function() { $(this).addClass("filter_select_item").next().show(); scanEvents(); filter(); returnfalse; //防止觸發原始網頁的查詢 }).on("click", ".fa-remove", function() { $(this).hide().prev().removeClass("filter_select_item"); scanEvents(); filter(); returnfalse; }); //執行篩選 function filter() { var $all = $(".com_detail_info"); $all.removeClass("show").hide(); //先全部隱藏 var selectedCatgs = $.map($filterBar.find(".filter_select_item"), function(elem) { //有選取的距離加上show var catgCss = $(elem).parent().attr("data-catg"); $all.filter("." + catgCss).addClass("show") }); $all.filter(".show").show(); //顯示有標上show者 } scanEvents(); |