Al_Caughey / EBird Daily Summary

// ==UserScript==
// @name         EBird Daily Summary
// @namespace    http://tampermonkey.net/
// @version      0.4.17
// @description  Inserts a table at the top of the eBirds alert page with the results sorted by location
// @author       Al Caughey (https://ebird.org/profile/Nzc4NDIy)
// @match        https://ebird.org/alert/summary*
// @require http://code.jquery.com/jquery-3.3.1.min.js
// @grant        none
// @license MIT
// ==/UserScript==

// v0.3.x - fixed sorting in Chrome 
// v0.4.x - added filtering by location 

(function () {
  'use strict';
  var $ = window.jQuery;
  
  window.jQuery.extend(
    window.jQuery.expr[':'].containsCI = function (a, i, m) {
      var sText = (a.textContent || a.innerText || "")
      var zRegExp = new RegExp(m[3], 'i')
      return zRegExp.test(sText)
    }
  )

  function debounce(fn, duration) {
    var timer
    return function () {
      clearTimeout(timer)
      timer = setTimeout(fn, duration)
    }
  }

  $(document).ready(function () {
    $('#al-summary').remove()
    $('.screenhead').after("<div id='al-summary'><h1>Al's Revised Summary<span style='font-size:small'>&nbsp;&nbsp;(<a href='#sightingsTable'>Original</a>)</span>&nbsp;&nbsp;</h1><table style='width:100%'><thead><tr><th><input type='text' id='filter-loc' placeholder='Filter by location...'></input></th><th><input type='text' id='filter-sp' placeholder='Filter by species...'></input>&nbsp;<span id='clear-filter' style='display:none'>X</span></th></thead id='al-summary-list'><tbody id='al-summary-list'></tbody></table></div>")
    $("<style type='text/css'> .hl{color:#f00;font-weight:bold;} .hlb{background:#0FF;font-weight:bold;width:max-content;} .hlb:before {content:'*';}#clear-filter{opacity:0.66;}#clear-filter:hover{cursor:pointer;opacity:1;}</style>").appendTo("head");

    var needslist = {}
    $('.has-details').each(function (index, value) {
      var species = $(value).find('.species-name a').text(),
        species_link = $(value).find('.species-name a').attr('href'),
        species_code = $(value).find('.species-name a').data('species-code'),
        date = $(value).find('.date').text().replace(' Checklist', ''),
        time = date.split(' ')[3],
        checklist = $(value).find('.date a').attr('href').split('/')[3],
        location = $(value).find('.location').text().replace(/Map/, '').replace(/Ottawa--/, '').replace(/Ottawa - /, ''),
        location_short = location.split(', ')[0].trim(),
        latlong_href = $(value).find('.location a').attr('href'),
        latlong = latlong_href.match(/ll=.*/)[0].replace(/ll=/, '')
      var ll = latlong.replace(/[-,\.]/g, '')
      if (!needslist[latlong]) {
        needslist[latlong] = {
          'name': location_short
        }
        $('#al-summary-list').append("<tr class='location-row showing' style='' id='" + ll + "' data-species-count='0'><td class='location-name' style='width:50%;vertical-align:top;border-top: 1px solid grey'><a href='" + latlong_href + "' target='_blank'>" + location_short + "</a><br/>Species Count: <span class='species-count' title='# species identified at this location'>##</span><br/>Lat/Long: " + latlong + "<br/><span class='checklists' title='Links to reporting checklist; sorted by time' style='display:flex;flex-wrap:wrap'>Checklists: </td><td class='location-species' style='width:50%;vertical-align:top;border-top: 1px solid grey;display:flex;flex-flow:column'></td></tr")
      }
      if (!needslist[latlong][species]) {
        needslist[latlong][species] = []
        $('#' + ll + ' .location-species').append("<a href='" + species_link + "' target='_blank' class='" + checklist + "' data-species-code='" + species_code + "'>" + species + "</a>")
        $('#' + ll).attr('data-species-count', $('#' + ll).attr('data-species-count') * 1 + 1)
      }
      else {
        $('#' + ll + ' .location-species').find('[data-species-code="' + species_code + '"]').addClass(checklist)
      }
      needslist[latlong][species].push({
        'checklist': checklist,
        'time': time
      })
      if (!$('#' + ll + " [data-checklist='" + checklist + "']").length) {
        // console.log(checklist, $('#' + ll + " [data-checklist='"+checklist+"']").length)
        $('#' + ll + ' .checklists').append("<a href='/view/checklist/" + checklist + "' target='_blank' data-checklist='" + checklist + "' style='padding-right:4px' title='" + date + "'>" + time + "</span>")
      }
    });
    var rows = $('.location-row')
    rows.sort(function (a, b) {
      var r1 = $(a).attr('data-species-count') * 1
      var r2 = $(b).attr('data-species-count') * 1
      return (r1 > r2 ? -1 : (r1 < r2 ? 1 : 0))
    });
    $.each(rows, function (index, row) {
      $('#al-summary-list').append(row)
      var checklists = $(row).find('.checklists a')
      $(row).find('.species-count').text($(row).attr('data-species-count'))
      checklists.sort(function (t1, t2) {
        var e1 = $(t1).text()
        var e2 = $(t2).text()
        return (e1 > e2 ? 1 : (e1 < e2 ? -1 : 0))
      })
      $.each(checklists, function (i, checklist) {
        $(row).find('.checklists').append(checklist)
      })
      var species = $(row).find('.location-species a')
      species.sort(function (t1, t2) {
        var e1 = $(t1).text()
        var e2 = $(t2).text()
        return (e1 > e2 ? 1 : (e1 < e2 ? -1 : 0))
      })
      $.each(species, function (i, bird) {
        $(row).find('.location-species').append(species)
      })
    });
    $('.checklists a').mouseenter(function () {
      var cc = $(this).data('checklist')
      $(this).parents('.location-row').find('.' + cc).addClass('hl')
    }).mouseleave(function () {
      var cc = $(this).data('checklist')
      $('.hl').removeClass('hl')
    })
    $('#filter-sp').keyup(debounce(function () {
      var st = $('#filter-sp').val()
      var all_r = $('.location-row')
      $('#filter-loc').fadeOut('slow')
      $('#clear-filter').fadeIn('slow')
      $('.hlb').removeClass('hlb')
      if (st == '') {
        all_r.show().slideDown('fast').addClass('showing')
        $('#filter-sp').fadeIn('slow')
        $('#clear-filter').fadeOut('slow')
      }
      else if (st.length < 2) {
        return false
      }
      else {
        all_r.not($('.location-species a:containsCI("' + st + '")').parents('tr')).hide().removeClass('showing');
        all_r.find($('.location-species a:containsCI("' + st + '")')).parents('tr').slideDown('fast').addClass('showing');
        $('.location-species a:containsCI("' + st + '")').addClass('hlb')
      }
    }, 333))

    $('#filter-loc').keyup(debounce(function () {
      var st = $('#filter-loc').val()
      var all_r = $('.location-row')
      $('#filter-sp').fadeOut('slow')
      $('#clear-filter').fadeIn('slow')
      if (st == '') {
        all_r.show().slideDown('fast').addClass('showing')
        $('#filter-sp').fadeIn('slow')
        $('#clear-filter').fadeOut('slow')
      }
      else if (st.length < 2) {
        return false
      }
      else {
        all_r.not($('.location-name a:containsCI("' + st + '")').parents('tr')).hide().removeClass('showing');
        all_r.find($('.location-name a:containsCI("' + st + '")')).parents('tr').slideDown('fast').addClass('showing');
      }
    }, 333))
    $('#clear-filter').click(function () {
      $('#clear-filter').fadeOut('slow')
      $('#filter-sp, #filter-loc').val('').fadeIn('slow')
      $('.location-row').slideDown('fast').addClass('showing')
    })
  })
})();