Greasy Fork is available in English.

Better ATND

ATNDをより便利にする

// ==UserScript==
// @name           Better ATND
// @namespace      http://efcl.info/
// @description    ATNDをより便利にする
// @include        http://atnd.org/events/*
// @include        https://atnd.org/events/*
// @version 0.2.0.20140518104253
// @grant GM_log
// @grant GM_xmlhttpRequest
// ==/UserScript==
/* TEST PAGE
 http://atnd.org/events/13389
 http://atnd.org/events/10996
 */
var DEBUG = false;
function log(m) {
    console.log(arguments);
}
var atndGM = {};
atndGM.eventID = window.location.pathname.split("/").pop();
(function () {
    // ATND APIからイベント情報取得
    function getEventJSON(eventID, callback) {
        if (typeof atndGM[atndGM.eventID] !== 'undefined') {
            callback(atndGM[atndGM.eventID]);
        } else {
            var endpoint = "http://api.atnd.org/events/?event_id=" + eventID + "&format=json";
            GM_xmlhttpRequest({
                method: "GET",
                url: endpoint,
                onload: function (res) {
                    var json = JSON.parse(res.responseText);
                    DEBUG && log(res.statusText, json);
                    atndGM[atndGM.eventID] = json;// キャッシュしておく
                    callback(json);
                },
                onerror: function (res) {
                    GM_log(res.statusText + " : " + res.responseText);
                }
            });
        }
    }

    // 緯度経度情報の取得
    function getGeoinfo(json) {
        var event = json.events[0].event;
        var lon = event.lon,
            lat = event.lat;
        DEBUG && log('lon' + lon, 'lat' + lat);
        if ((lon && lat)
            && (parseFloat(lon) != 0.0 && parseFloat(lat) != 0.0)) {
            // 緯度経度情報が取得できた場合は最寄り駅を取得する
            return {
                'lon': lon,
                'lat': lat
            };
        }
    }

    // 緯度経度から最寄り駅情報を取得
    function getNearsideStation(geo, callback) {
        var endpoint = "http://map.simpleapi.net/stationapi?x=" + String(geo.lon) + "&y=" + String(geo.lat) + "&output=json";
        var count = 0;
        GM_xmlhttpRequest({
            method: "GET",
            url: endpoint,
            onload: function (res) {
                var json = JSON.parse(res.responseText),
                    resultHTML = document.createDocumentFragment();
                var dl = document.createElement('dl');
                dl.setAttribute('class', "clearfix station-info");
                DEBUG && log("near Stations JSON", json);
                for (var i = 0, len = json.length; i < len; i++) {
                    var name = json[i].name;
                    var line = json[i].line;
                    var distance = json[i].distanceKm || json[i].distanceM;
                    var traveltime = json[i].traveltime;
                    var stationInfo = line + "/" + name + "/" + distance + "/" + traveltime;

                    var dt = document.createElement('dt');
                    dt.innerHTML = "最寄り駅 / ST:";
                    var dd = document.createElement('dd');
                    dd.appendChild(document.createTextNode(stationInfo));
                    dl.appendChild(dt);
                    dl.appendChild(dd);
                }
                resultHTML.appendChild(dl);
                DEBUG && log("resultHTML", resultHTML);
                callback(resultHTML);
            },
            onerror: function (res) {
                GM_log(res.statusText + " : " + res.responseText);
            }
        });

    }

    function getStationHTML(callback) {
        getEventJSON(atndGM.eventID, function (res) {
            atndGM.st.geo = getGeoinfo(res);
            if (atndGM.st.geo) {
                getNearsideStation(atndGM.st.geo, function (resHTML) {
                    DEBUG && log("getStationHTML", resHTML);
                    callback(resHTML);
                });
            } else {
                DEBUG && log("getStationHTML : GEO INFO doesn't exist");
                callback();
            }
        });
    }


    atndGM.st = {
        'getEventJSON': getEventJSON,
        'getNearsideStation': getNearsideStation,
        'getStationHTML': getStationHTML
    };
})();
(function gCal() {
    function formatToUTCDate(jstDateTime) {
        if (!jstDateTime) {
            return;
        }
        var dateTime = jstDateTime.replace(/[-,:]/g, "").replace(/.....$/, "");
        var jstDate = Number(dateTime.slice(0, 8));
        var jstTime = Number(dateTime.slice(9, 15));
        var utcDate;
        if (jstTime < 90000) {
            utcDate = jstDate - 1;
        } else {
            utcDate = jstDate;
        }
        var utcTime = String((jstTime + 240000 - 90000) % 240000);
        utcTime = utcTime.length == 6 ? utcTime : '0' + utcTime;
        return utcDate + 'T' + utcTime + 'Z';
    }

    function createCalendarLink(json) {
        json = json || atndGM[atndGM.eventID] || atndGM.st.getEventJSON(createCalendarLink);
        var event = json.events[0].event;// イベントの情報が入ってる
        var descrition = location.href + '\n_' + document.getElementById("post-body").textContent.trim();// API経由だと記法が入ってしまう
        if ("catch" in event) {
            descrition = event["catch"] + "\n" + descrition;// キャッチを追加する
        }
        var description = encodeURIComponent((descrition.length < 300) ? // 文字数が多いとRequest-URI Too Largeになる
                                             descrition : descrition.substring(0, 100) + '...');
        var title = encodeURIComponent(event.title),
            started_at = formatToUTCDate(event.started_at || ""),
            ended_at = formatToUTCDate(event.ended_at || ""),
            address = encodeURIComponent(event.address || "");

        var dates = "&dates=" + started_at + "/"
        if (ended_at) {
            dates += ended_at;
        } else {
            dates += started_at;// ないなら開始時間と同じ
        }
        // カレンダーリンクを生成
        var link = document.createElement('a');
        link.innerHTML = "<img src='http://www.google.com/calendar/images/ext/gc_button1_ja.gif' border=0></a>";
        link.setAttribute('href',
                'https://www.google.com/calendar/event?action=TEMPLATE&text=' + title
                + dates
                + "&details=" + description + "&location=" + address + "&trp=false&sprop=website:atnd.org&sprop;=name:ATND");
        return link;
    }

    atndGM.gCal = {
        'createCalendarLink': createCalendarLink
    }
})();
(function main() {
    var insertArea = document.querySelector('#events-show > div.main');
    var stationArea = insertArea.querySelector('div.events-show-info');
    var mapArea = insertArea.querySelector('div.events-show-map');
    atndGM.st.getStationHTML(function (stationHTML) {
        if (typeof stationHTML !== 'undefined') {
            stationArea.appendChild(stationHTML);
            var stationMapImg = document.createElement("img");
            stationMapImg.src = "http://map.simpleapi.net/stationmap?x=" + atndGM.st.geo.lon + "&y=" + atndGM.st.geo.lat;
            mapArea.appendChild(stationMapImg);
        }
        // Google Calendar
        var title_ul = document.querySelector('div.title-btn > ul');
        var link = atndGM.gCal.createCalendarLink();
        var li = document.createElement("li");
        li.appendChild(link);
        title_ul.appendChild(li);
    });

})();