Geocaching.com

Adds links and data to Geocaching.com to make it more user friendly

当前为 2016-03-16 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

/* global $: true */
/* global waitForKeyElements: true */
/* global GM_xmlhttpRequest: true */
/* global unsafeWindow: true */
// jshint newcap:false
// jshint multistr:true

// ==UserScript==
// @name        Geocaching.com
// @namespace   GeocachingWebsiteScript
// @description Adds links and data to Geocaching.com to make it more user friendly
// @include     http://www.geocaching.com/*
// @include     https://www.geocaching.com/*
// @version     1.0.0
// @require     http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js
// @require     https://greasyfork.org/scripts/5392-waitforkeyelements/code/WaitForKeyElements.js?version=19641
// @grant       GM_xmlhttpRequest
// @license     The MIT License (MIT)
// ==/UserScript==


(function() {

    'use strict';

    var pgcUrl = 'http://project-gc.com/',
        pgcApiUrl = pgcUrl + 'api/gm/v1/',
        externalLinkIcon = 'http://maxcdn.project-gc.com/images/external_small.png',
        galleryLinkIcon = 'http://maxcdn.project-gc.com/images/pictures_16.png',
        mapLinkIcon = 'http://maxcdn.project-gc.com/images/map_app_16.png',                
        latestLogs = [],
        latestLogsAlert = false,        
        path = window.location.pathname;

    // Don't run the script for iframes
    if (window.top == window.self) {
        MainFunction();
    }

    function MainFunction() {                
        RemoveAdsFromPage();
        Router();
    }    

    function RemoveAdsFromPage() {        
        $('#ctl00_uxBanManWidget').remove();        
        $('#ctl00_ContentBody_uxBanManWidget').remove();         
    }

    function Router() {
        if (path.match(/^\/geocache\/.*/) !== null) {
            Page_CachePage();
        } else if (path.match(/^\/seek\/cache_details\.aspx.*/) !== null) {
            Page_CachePage();
        } else if (path.match(/^\/seek\/cache_logbook\.aspx.*/) !== null) {
            Page_Logbook();  
        } else if (path.match(/^\/seek\/log\.aspx.*/) !== null) {
            Page_NewLog();        
        } 
    }   

    function getGcCodeFromPage() {
        return $('#ctl00_ContentBody_CoordInfoLinkControl1_uxCoordInfoCode').html();
    }

    function getGccomUsername(){
        var gccomUsername = null;
        if ($('#ctl00_uxLoginStatus_divSignedIn ul.logged-in-user').length) {
            gccomUsername = $('#ctl00_uxLoginStatus_divSignedIn ul.logged-in-user .li-user-info span').html();
        } else if ($('ul.profile-panel-menu').length) {
            gccomUsername = $('ul.profile-panel-menu .li-user-info span:nth-child(2)').text();
        } else if ($('#uxLoginStatus_divSignedIn ul.logged-in-user li.li-user span.li-user-info span').first().text().length) {
            gccomUsername = $('#uxLoginStatus_divSignedIn ul.logged-in-user li.li-user span.li-user-info span').first().text();
        }
        return gccomUsername;
    }

    function MetersToFeet(meters) {
        return Math.round(meters * 3.28084);
    }

    function FormatDistance(distance) {
        distance = parseInt(distance, 10);        
        distance = distance.toLocaleString();
        return distance;
    }

    function getCoordinates() {
        return $('#ctl00_ContentBody_MapLinks_MapLinks li a').attr('href');
    }

    function getLatitude(coordinates) {        
        return coordinates.replace(/.*lat=([^&]*)&lng=.*/, "$1");        
    }

    function getLongitude(coordinates) {        
        return coordinates.replace(/.*&lng=(.*)$/, "$1");
    }

    function getGeocachingMapURL(latitude, longitude) {   
        return 'https://www.geocaching.com/map/default.aspx?lat='+latitude+'&lng='+longitude+'&z=16';
    }

    function getGoogleMapURL(latitude, longitude) {
        return 'http://maps.google.com/maps?q='+latitude+','+longitude;              
    }

    function getGoogleMapStreetViewURL(latitude, longitude) {       
        return getGoogleMapURL(latitude,longitude) + "&layer=c&cbll=" + latitude + ',' + longitude + '&cbp=11,0,0,0,0';
    }

    function getBingBirdsEyeViewURL(latitude, longitude) {       
        return "http://bing.com/maps/default.aspx?cp="+latitude+"~"+longitude+"&style=o&lvl=20";
    }

    function addOtherInfoDiv(username,latitude,longitude) {        
        var ownerName = $('#ctl00_ContentBody_mcd1 a').html();
        var ownerProfile = $('#ctl00_ContentBody_mcd1 a').attr('href');        
        var ownerProfileGCLink = '<a href="' + pgcUrl + 'ProfileStats/' + encodeURIComponent(ownerName) + '" target="_blank"><img src="' + externalLinkIcon + '" title="PGC Profile Stats"></a>';                                                                                  

        var result = "<div id='otherInfo'>";        

        result += 'Ver a cache no <a href=' + getGeocachingMapURL(latitude,longitude) + " target='_blank'>Mapa Geocaching</a>";
        result += ', no <a href=' + getGoogleMapURL(latitude,longitude) + " target='_blank'>Google Maps</a>";
        result += ', no <a href=' + getGoogleMapStreetViewURL(latitude,longitude) + " target='_blank'>Street View</a>";
        result += ', no <a href=' + getBingBirdsEyeViewURL(latitude,longitude) + " target='_blank'>Bird's eye View</a>";

        var urlOwnerCaches = "<a href='https://www.geocaching.com/play/search?origin=Portugal&ot=2&g=159&types=2,3,8,137,5,11,1858,4,9,3773&owner[0]="+ownerName+"&sort=PlaceDate&asc=False' target='_blank'>todas as geocaches</a>";
        result += "<br>Pesquisar <a href='" + ownerProfile + "' target='_blank'>"+ ownerName + "</a> " + ownerProfileGCLink + urlOwnerCaches;

        var urlOwnerActiveCaches = "<a href='https://www.geocaching.com/play/search?origin=Portugal&ot=2&g=159&types=2,3,8,137,5,11,1858,4,9,3773&owner[0]="+ownerName+"&e=1&sort=PlaceDate&asc=False' target='_blank'>apenas as activas</a>";
        result += ', ' + urlOwnerActiveCaches;

        var urlOwnerNotFoundByMe = "<a href='https://www.geocaching.com/play/search?nfb[0]="+username+"&owner[0]="+ownerName+"&f=2' target='_blank'>as que ainda não encontrei</a>";
        result += ', ' + urlOwnerNotFoundByMe;        

        $('#ctl00_ContentBody_CacheInformationTable').append(result + "</div>");
    }

    function correctComboValues(){
        var xpto = $('#ctl00_ContentBody_LogBookPanel1_ddLogType').html();
        xpto = xpto.replace("Found it", "Encontrada");
        xpto = xpto.replace("Didn't find it", "Não encontrada");
        xpto = xpto.replace("Write note", "Escrever nota");
        xpto = xpto.replace("Will Attend", "Irei participar");
        xpto = xpto.replace("Attended", "Participei");
        xpto = xpto.replace("Needs Archived", "Pedido de arquivamento");
        xpto = xpto.replace("Needs Maintenance", "Pedido de manutenção");
        xpto = xpto.replace("Archive", "Arquivar");
        xpto = xpto.replace("Temporarily Disable Listing", "Desativar");
        xpto = xpto.replace("Update Coordinates", "Atualizar coordenadas");
        xpto = xpto.replace("Owner Maintenance", "Manutenção efetuada");
        $('#ctl00_ContentBody_LogBookPanel1_ddLogType').html(xpto);
    }

    function tidyTheWeb(){
        //$('#lnkMessageOwner').html('');
        $('#ctl00_divContentMain p.Clear').css('margin', '0');
        $('div.Note.PersonalCacheNote').css('margin', '0');         
        //$('h3.CacheDescriptionHeader').remove();
        $('#ctl00_ContentBody_EncryptionKey').remove();
        $('#div_hint').css('margin-bottom', '25px');            
        $('.CacheInformationTable .LocationData').css('border-bottom', '0');      
    }

    // Make it easier to copy the gccode
    function makeCopyFriendly(gccode){
        $('#ctl00_ContentBody_CoordInfoLinkControl1_uxCoordInfoLinkPanel').
        html('<div style="margin-right: 15px; margin-bottom: 10px;"><p id="ctl00_ContentBody_CoordInfoLinkControl1_uxCoordInfoCode" style="font-size: 125%; margin-bottom: 0">' + gccode + '</p>' +
             '<input size="25" type="text" value="http://coord.info/' + encodeURIComponent(gccode) + '" onclick="this.setSelectionRange(0, this.value.length);"></div>');
        $('#ctl00_ContentBody_CoordInfoLinkControl1_uxCoordInfoLinkPanel').css('font-weight', 'inherit').css('margin-right', '39px');
        $('#ctl00_ContentBody_CoordInfoLinkControl1_uxCoordInfoLinkPanel div').css('margin', '0 0 15px 0');
        $('#ctl00_ContentBody_CoordInfoLinkControl1_uxCoordInfoLinkPanel div p').css('font-weight', 'bold');
    }

    function removeUTMCoordinates(){               
        $('#ctl00_ContentBody_LocationSubPanel').html('');

        // And move the "N 248.3 km from your home location"
        //$('#ctl00_ContentBody_LocationSubPanel').after($('#lblDistFromHome'));       
    }

    function resolveCoordinatesIntoAnAddress(latitude, longitude){         
        var url = 'http://maps.googleapis.com/maps/api/geocode/json?latlng=' + latitude + ',' + longitude + '&sensor=false';

        GM_xmlhttpRequest({
            method: "GET",
            url: url,
            onload: function(response) {
                var result = JSON.parse(response.responseText);
                if (result.status !== 'OK') {
                    return false;
                }
                var formattedAddress = result.results[0].formatted_address;
                $('#ctl00_ContentBody_LocationSubPanel').append(formattedAddress + '<br />');
            }
        });

    }

    function Page_CachePage() {
        var username = getGccomUsername();
        var gccode = getGcCodeFromPage();     
        var coordinates = getCoordinates();
        var latitude = getLatitude(coordinates);
        var longitude = getLongitude(coordinates);                          

        // Since everything in the logbook is ajax, we need to wait for the elements
        waitForKeyElements('#cache_logs_table tr', Logbook);

        tidyTheWeb();               
        makeCopyFriendly(gccode);        

        // Add other info
        addOtherInfoDiv(username,latitude,longitude);

        // Remove the UTM coordinates
        removeUTMCoordinates();

        // Remove disclaimer
        //$('#ctl00_divContentMain div.span-17 div.Note.Disclaimer').remove();
        $('#divContentMain div.Note.Disclaimer').remove();                                          

        // Resolve the coordinates into an address
        resolveCoordinatesIntoAnAddress(latitude, longitude);               

        // Add number of finds per type to the top
        addNumberOfFindsPerType();

        // Add map links for each bookmarklist        
        addMapLinksForEachBookmarkList();

        // Decrypt the hint
        unsafeWindow.dht();

    }

    function addNumberOfFindsPerType(){
        if (typeof $('#ctl00_ContentBody_lblFindCounts').html() !== 'undefined') {
            $('#ctl00_ContentBody_CacheInformationTable').before('<div>' + $('#ctl00_ContentBody_lblFindCounts').html() + '</div>');
        }
    }

    function addMapLinksForEachBookmarkList(){
        var url = '';
        $('ul.BookmarkList li').each(function() {
            var guid = $(this).children(':nth-child(1)').attr('href').replace(/.*\?guid=(.*)/, "$1");
            var owner = $(this).children(':nth-child(3)').text();            

            // Add the map link
            url = 'http://project-gc.com/Tools/MapBookmarklist?owner_name=' + encodeURIComponent(owner) + '&guid=' + encodeURIComponent(guid);
            $(this).children(':nth-child(1)').append('&nbsp;<a href="' + url + '" target="_blank"><img src="' + mapLinkIcon + '" title="Map with Project-GC"></a>');               

            // Add profile stats link to the owner
            url = 'http://project-gc.com/ProfileStats/' + encodeURIComponent(owner);
            $(this).children(':nth-child(3)').append('&nbsp;<a href="' + url + '" target="_blank"><img src="' + externalLinkIcon + '" title="Project-GC Profile stats"></a>');
        });

    }    

    function Page_Logbook() {                
        // Since everything in the logbook is ajax, we need to wait for the elements
        waitForKeyElements('#AllLogs tr', Logbook);
        waitForKeyElements('#PersonalLogs tr', Logbook);
        waitForKeyElements('#FriendLogs tr', Logbook);
    }

    function Page_NewLog() {        
        correctComboValues();
        if($('#ctl00_ContentBody_lbHeading').html()!='Efectuar um registo'){
            // do nothing            
        } 
        else 
        {      
            var cachesCount = $('.cache-count').html();
            cachesCount = cachesCount.substring(0,cachesCount.indexOf(' '));
            cachesCount++;

            if(document.title.includes('Event')){
                //$('#ctl00_ContentBody_LogBookPanel1_uxLogInfo').append("**#"+cachesCount+"**\n\nMais um momento de convívio com o pessoal do costume onde falámos deste nosso hobby e partilhámos alguns TB's!\n\nObrigado ao owner pela iniciativa e até ao próximo evento ;-)\n\n**TFTE!**"); 
            } else {                              
                //$('#ctl00_ContentBody_LogBookPanel1_uxLogInfo').append("**#"+cachesCount+"**\n\nCache encontrada na companhia de...\nObrigado ao owner pela cache e partilha do local ;-)\n\n**TFTC!**");
                $('#ctl00_ContentBody_LogBookPanel1_uxLogInfo').append("**#"+cachesCount+"**\n\nCache encontrada na companhia de...\n\n\n\n**TFTC!**");
            }

        }
    }

    function addProfileStatsForUser(jNode) {
        var profileNameElm = $(jNode).find('p.logOwnerProfileName strong a');
        var profileName = profileNameElm.html();

        if (typeof profileName !== 'undefined') {
            profileName = profileNameElm.append('<a href="' + pgcUrl + 'ProfileStats/' + encodeURIComponent(profileName) + '" target="_blank"><img src="' + externalLinkIcon + '" title="PGC Profile Stats"></a>');                                            
        }
    }

    function Logbook(jNode) {
        // Add Profile stats after each user
        addProfileStatsForUser(jNode);

        // Save to latest logs
        if (latestLogs.length < 5) {
            var node = $(jNode).find('div.HalfLeft.LogType strong img[src]'),
                logType = {};

            if (node.length === 0)
                return false;

            logType = {
                'src': node.attr('src'),
                'alt': node.attr('alt'),
                'title': node.attr('title')
            };

            logType.id = +logType.src.replace(/.*logtypes\/(\d+)\.png/, "$1");

            // First entry is undefined, due to ajax
            if (logType.src) {
                latestLogs.push('<img src="' + logType.src + '" alt="' + logType.alt + '" title="' + logType.title + '" style="margin-bottom: -4px; margin-right: 1px;">');
                // 2 = found, 3 = dnf, 4 = note, 5 = archive, 22 = disable, 24 = publish, 45 = nm, 46 = owner maintenance, 68 = reviewer note
                if ($.inArray(logType.id, [3, 5, 22, 45, 68]) !== -1) {
                    latestLogsAlert = true;
                }
            }

            // Show latest logs
            // TODO : Fix this code => latestLogs.length === 5 but it's < 5 higher...
            if (latestLogs.length === 5) {
                var images = latestLogs.join('');

                $('#ctl00_ContentBody_size p').removeClass('AlignCenter').addClass('NoBottomSpacing');

                if (latestLogsAlert) {
                    $('#ctl00_ContentBody_size').append('<p class="NoBottomSpacing OldWarning"><strong>Latest logs:</strong> <span>' + images + '</span></p>');
                } else {
                    $('#ctl00_ContentBody_size').append('<p class="NoBottomSpacing">Latest logs: <span>' + images + '</span></p>');
                }
            }

        }

    }


    //TODO - add live map
    function addPgcLiveMap(latitude,longitude){
        // var mapUrl = pgcUrl + 'Maps/mapcompare/?profile_name=' + gccomUsername +
        //     '&nonefound=on&ownfound=on&location=' + latitude + ',' + longitude +
        //     '&max_distance=5&submit=Filter';
        var mapUrl = pgcUrl + 'LiveMap/#c=' + latitude + ',' + longitude + ';z=14';

        // $('#ctl00_ContentBody_CoordInfoLinkControl1_uxCoordInfoLinkPanel').append(
        //     '<div style="margin-bottom: 8px;"><a target="_blank" href="' + mapUrl + '">Project-GC map</a> (<a target="_blank" href="' + mapUrl + '&onefound=on">incl found</a>)</div>'
        // );
        $('#ctl00_ContentBody_CoordInfoLinkControl1_uxCoordInfoLinkPanel').append(
            '<div style="margin-bottom: 8px;"><a target="_blank" href="' + mapUrl + '">Project-GC Live map</a></div>'
        );

    }

    //TODO - add map compare links
    function addPgcMapLinks(username,latitude,longitude){        
        var max_distance = 3;
        var playerToCompare = 'player1';

        var mapUrl = pgcUrl + 'Tools/MapCompare/?profile_name='+username+'&profile_name2='+playerToCompare+'&' +
            'nonefound=on&onefound=on&ownfound=on&location=' + latitude + ',' + longitude + '&max_distance=4&' +                 
            'type%5B%5D=Earthcache&type%5B%5D=GPS+Adventures+Exhibit&type%5B%5D=Groundspeak+Block+Party&type%5B%5D=Groundspeak+HQ&type%5B%5D=Groundspeak+Lost+and+Found+Celebration&type%5B%5D=Letterbox+Hybrid&type%5B%5D=Locationless+%28Reverse%29+Cache&type%5B%5D=Lost+and+Found+Event+Cache&type%5B%5D=Multi-cache&type%5B%5D=Project+APE+Cache&type%5B%5D=Traditional+Cache&type%5B%5D=Unknown+Cache&type%5B%5D=Virtual+Cache&type%5B%5D=Webcam+Cache&type%5B%5D=Wherigo+Cache&submit=Filter';                            
        $('#ctl00_ContentBody_CoordInfoLinkControl1_uxCoordInfoLinkPanel').append(
            '<div style="margin-bottom: 8px;"><a target="_blank" href="' + mapUrl + '">Map Compare with '+playerToCompare+'</a></div>'
        );

        playerToCompare = 'player2';
        mapUrl = pgcUrl + 'Tools/MapCompare/?profile_name='+username+'&profile_name2='+playerToCompare+'&' +
            'nonefound=on&onefound=on&ownfound=on&location=' + latitude + ',' + longitude + '&max_distance=4&' +                 
            'type%5B%5D=Earthcache&type%5B%5D=GPS+Adventures+Exhibit&type%5B%5D=Groundspeak+Block+Party&type%5B%5D=Groundspeak+HQ&type%5B%5D=Groundspeak+Lost+and+Found+Celebration&type%5B%5D=Letterbox+Hybrid&type%5B%5D=Locationless+%28Reverse%29+Cache&type%5B%5D=Lost+and+Found+Event+Cache&type%5B%5D=Multi-cache&type%5B%5D=Project+APE+Cache&type%5B%5D=Traditional+Cache&type%5B%5D=Unknown+Cache&type%5B%5D=Virtual+Cache&type%5B%5D=Webcam+Cache&type%5B%5D=Wherigo+Cache&submit=Filter';                            
        $('#ctl00_ContentBody_CoordInfoLinkControl1_uxCoordInfoLinkPanel').append(
            '<div style="margin-bottom: 8px;"><a target="_blank" href="' + mapUrl + '">Map Compare with '+playerToCompare+'</a></div>'
        );

        playerToCompare = 'player3';
        mapUrl = pgcUrl + 'Tools/MapCompare/?profile_name='+username+'&profile_name2='+playerToCompare+'&' +
            'nonefound=on&onefound=on&ownfound=on&location=' + latitude + ',' + longitude + '&max_distance=4&' +                 
            'type%5B%5D=Earthcache&type%5B%5D=GPS+Adventures+Exhibit&type%5B%5D=Groundspeak+Block+Party&type%5B%5D=Groundspeak+HQ&type%5B%5D=Groundspeak+Lost+and+Found+Celebration&type%5B%5D=Letterbox+Hybrid&type%5B%5D=Locationless+%28Reverse%29+Cache&type%5B%5D=Lost+and+Found+Event+Cache&type%5B%5D=Multi-cache&type%5B%5D=Project+APE+Cache&type%5B%5D=Traditional+Cache&type%5B%5D=Unknown+Cache&type%5B%5D=Virtual+Cache&type%5B%5D=Webcam+Cache&type%5B%5D=Wherigo+Cache&submit=Filter';                            
        $('#ctl00_ContentBody_CoordInfoLinkControl1_uxCoordInfoLinkPanel').append(
            '<div style="margin-bottom: 8px;"><a target="_blank" href="' + mapUrl + '">Map Compare with '+playerToCompare+'</a></div>'
        );

    }


}());