eBird Acornizer

Custom tags and improved rating display for eBird media.

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

Bạn sẽ cần cài đặt một tiện ích mở rộng như Tampermonkey hoặc Violentmonkey để cài đặt kịch bản này.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(Tôi đã có Trình quản lý tập lệnh người dùng, hãy cài đặt nó!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name         eBird Acornizer
// @namespace    https://github.com/balagansky/
// @version      2025-11-15
// @description  Custom tags and improved rating display for eBird media.
// @author       Ruslan Balagansky
// @license	     MIT
// @match        https://media.ebird.org/catalog*
// @match        https://macaulaylibrary.org/asset/*
// @icon         data:image/png;base64,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
// @grant        GM.getValue
// @grant        GM.setValue
// @grant        GM.listValues
// @grant        GM.registerMenuCommand
// @grant		 GM.setClipboard
// @run-at	   	 document-end
// ==/UserScript==

var settings;
var favorites;
var goods;
var alternates;
var funnies;
var stares;

const cMaxAutoLoad = 500;

// import/export functions
function importFavorites() {
	var dataStr = prompt("Enter data (exported with Export function): ");
	try {
		var data = JSON.parse(dataStr);
		for (const key in data) {
			GM.setValue(key, data[key]);
			console.log("Saved data for key: " + key);
		}
		
		alert("Data imported! Refresh the page to see changes.");
	} catch (e) {
		alert("Failed to import data. Please check the format and try again.");
	}
}

function exportFavorites() {
	GM.listValues().then(async function(keys) {
		var data = {};
		for (const key of keys) {
			data[key] = await GM.getValue(key);
			console.log("Loaded data for key: " + key);
		}

		GM.setClipboard(JSON.stringify(data), "text").then(function() {
			alert("Exported data to clipboard.");
		});
	});
}

GM.registerMenuCommand("Import Tags", importFavorites);
GM.registerMenuCommand("Export Tags", exportFavorites);


async function readFromStorage(key)
{
	try {
		// GM.getValue returns the stored value directly; don't JSON.parse it
		var readResult = await GM.getValue(key);
		var valueStr = JSON.stringify(readResult);
		if (valueStr)
			valueStr = valueStr.slice(0, 100) + "...";
		console.log("read " + key + ": " + valueStr);
		return readResult;
	} catch (e) {
		console.log("error reading " + key + ". Maybe not written yet?");
		return null;
	}
}

async function saveToStorage(key, value)
{
	// stringify once for logging only
	var valueStr = JSON.stringify(value);
	if (valueStr)
		valueStr = valueStr.slice(0, 100) + "...";
	console.log("saving " + key + ": " + valueStr);
	await GM.setValue(key, value);
	console.log(key + " saved");
}

async function readSettings()
{
	var readSettings = await readFromStorage("settings");
	settings = readSettings || {
		maxResults: 100
	};
}

async function saveSettings()
{
	await saveToStorage("settings", settings);
}

async function readFavorites()
{
	var readFavorites = await readFromStorage("favorites");
	favorites = new Set();
	if (readFavorites) {
		try {
			favorites = new Set(readFavorites);
		} catch {}
	}
	
	var readGoods = await readFromStorage("goods");
	goods = new Set();
	if (readGoods) {
		try {
			goods = new Set(readGoods);
		} catch {}
	}
	
	var readAlternates = await readFromStorage("alternates");
	alternates = new Set();
	if (readAlternates) {
		try {
			alternates = new Set(readAlternates);
		} catch {}
	}
	
	var readFunnies = await readFromStorage("funnies");
	funnies = new Set();
	if (readFunnies) {
		try {
			funnies = new Set(readFunnies);
		} catch {}
	}
	
	var readStares = await readFromStorage("stares");
	stares = new Set();
	if (readStares) {
		try {
			stares = new Set(readStares);
		} catch {}
	}
}

async function saveFavorites()
{
	await saveToStorage("favorites", Array.from(favorites));
	await saveToStorage("goods", Array.from(goods));
	await saveToStorage("alternates", Array.from(alternates));
	await saveToStorage("funnies", Array.from(funnies));
	await saveToStorage("stares", Array.from(stares));
}

async function readStorage()
{
	await readSettings();
	await readFavorites();
}

function isViewSupported() {
	var resultsGrid = document.getElementsByClassName("ResultsGrid");
	if (resultsGrid.length == 0) {
		console.log("Only grid views are supported.");
		return false;
	}
	return true;
}

var results = [];
var resultIds = new Set();
var resultOrigOrder = {};
var resultRatings = {};

function clearResults() {
	results = [];
	resultIds = new Set();
	resultOrigOrder = {};
}

var additionalLoadCount = 0;
const cImagesPerLoad = 30;

function loadMoreResults() {
	if (results.length == 0)
		return;
	
	var pagination = document.getElementsByClassName("pagination")[0];
	for (var pagChild of pagination.childNodes) {
		if (pagChild.type == "button") {
			if (results.length >= settings.maxResults) {
				console.log("Result limit reached.");
			} else if (additionalLoadCount > settings.maxResults / cImagesPerLoad) {
				console.log("Safety additional load limit reached");
			} else if (isViewSupported()) {
				console.log("loading more results");
				pagChild.click();
				additionalLoadCount += 1;
			}
			break;
		}
	}
}

function getResultId(result) {
	return result.querySelector("[data-asset-id]").getAttribute("data-asset-id");
}

function getNumRatings(result) {
	var ratings = result.querySelector(".RatingStars-count");
	if (!ratings)
		return 0;
	return Number(result.querySelector(".RatingStars-count").textContent.match(/\d+/));
}

function getStarRating(result) {
	var stars = result.querySelector(".RatingStars");
	if (!stars)
		return 0;
	return Number(stars.querySelector("[class=is-visuallyHidden]").textContent.match(/\d+/));
}

function getCheckboxState(result, checkboxClassName) {
	var checkBox = result.getElementsByClassName(checkboxClassName)[0];
	return checkBox && checkBox.checked;
}

function getAcornRating(result) {
	if (getCheckboxState(result, "favCheck"))
		return 3;
	if (getCheckboxState(result, "goodCheck"))
		return 2;
	return 0;
}

function getAlternateRating(result) { return getCheckboxState(result, "altCheck");} 
function getFunnyRating(result) { return getCheckboxState(result, "funnyCheck");} 
function getStareRating(result) { return getCheckboxState(result, "stareCheck");} 

function getOriginalOrder(result) {
	return resultOrigOrder[getResultId(result)];
}

const cEncodedIcon = 'data:image/png;base64,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'
var iconStyles = new Set();

function createAcornizerIconElement(size)
{
	if (!iconStyles[size]) {
		iconStyles.add(size);
		const iconStyle = document.createElement('style')
		iconStyle.textContent = `
		span.acornizer-icon-${size}::before {
			background-image: url("${cEncodedIcon}");
			content: "";
			background-repeat: no-repeat;
			background-size: ${size}px ${size}px;
			width: ${size}px;
			height: ${size}px;
			margin-right: 2px;
			display: inline-block;
		}`;
		document.head.appendChild(iconStyle);
	}

	var span = document.createElement("span");
	span.classList.add(`acornizer-icon-${size}`);
	return span;
}

function readNewCards() {
	var resultItems = document.getElementsByClassName("ResultsGrid-card");
	var gotNewResult = false;
	var cardOrder = 1;
	for (var result of resultItems) {
		const resultId = getResultId(result);
		if (!resultIds.has(resultId))
		{
			resultOrigOrder[resultId] = cardOrder;
			
			gotNewResult = true;
			//console.log("num ratings " + getNumRatings(result));
			//console.log("rating " + getStarRating(result));
			resultIds.add(resultId);
			// NOTE: cloning breaks site code. Have to manipulate in place.
			results.push(result);
			
			// add acornizer controls
			var capDiv = result.getElementsByClassName("ResultsGrid-caption")[0];
			if (capDiv.getElementsByClassName("favDiv").length == 0) {
				// add fav div
				var userDiv = capDiv.getElementsByClassName("userDateLoc")[0];
				var favDiv = document.createElement("div");
				favDiv.classList.add("favDiv");
				capDiv.insertBefore(favDiv, userDiv);
				
				favDiv.appendChild(createAcornizerIconElement(20));
				
				var favCheck = document.createElement("input");
				favCheck.classList.add("favCheck");
				favCheck.setAttribute("type", "checkbox");
				favCheck.checked = favorites.has(resultId);
				favCheck.addEventListener("change", (e) => {
					if (e.target.checked) {
						favorites.add(resultId);
						goods.delete(resultId);
						alternates.delete(resultId);
						e.target.parentElement.getElementsByClassName("goodCheck")[0].checked = false;
						e.target.parentElement.getElementsByClassName("altCheck")[0].checked = false;
					} else {
						favorites.delete(resultId);
					}
					saveFavorites();
					updateOrdering();
					});
				favDiv.appendChild(favCheck);
				favDiv.appendChild(document.createTextNode("Favorite "));
				
				var goodCheck = document.createElement("input");
				goodCheck.classList.add("goodCheck");
				goodCheck.setAttribute("type", "checkbox");
				goodCheck.checked = goods.has(resultId);
				goodCheck.addEventListener("change", (e) => {
					if (e.target.checked) {
						goods.add(resultId);
						favorites.delete(resultId);
						alternates.delete(resultId);
						e.target.parentElement.getElementsByClassName("favCheck")[0].checked = false;
						e.target.parentElement.getElementsByClassName("altCheck")[0].checked = false;
					} else {
						goods.delete(resultId);
					}
					saveFavorites();
					updateOrdering();
					});
				favDiv.appendChild(goodCheck);
				favDiv.appendChild(document.createTextNode("Good "));
				
				var altCheck = document.createElement("input");
				altCheck.classList.add("altCheck");
				altCheck.setAttribute("type", "checkbox");
				altCheck.checked = alternates.has(resultId);
				altCheck.addEventListener("change", (e) => {
					if (e.target.checked) {
						alternates.add(resultId);
						goods.delete(resultId);
						favorites.delete(resultId);
						e.target.parentElement.getElementsByClassName("goodCheck")[0].checked = false;
						e.target.parentElement.getElementsByClassName("favCheck")[0].checked = false;
					} else {
						alternates.delete(resultId);
					}
					saveFavorites();
					updateOrdering();
					});
				favDiv.appendChild(altCheck);
				favDiv.appendChild(document.createTextNode("Alternate "));
				
				var funnyCheck = document.createElement("input");
				funnyCheck.classList.add("funnyCheck");
				funnyCheck.setAttribute("type", "checkbox");
				funnyCheck.checked = funnies.has(resultId);
				funnyCheck.addEventListener("change", (e) => {
					if (e.target.checked) {
						funnies.add(resultId);
					} else {
						funnies.delete(resultId);
					}
					saveFavorites();
					updateOrdering();
					});
				favDiv.appendChild(document.createTextNode(" | "));
				favDiv.appendChild(funnyCheck);
				favDiv.appendChild(document.createTextNode("Funny "));
				
				var stareCheck = document.createElement("input");
				stareCheck.classList.add("stareCheck");
				stareCheck.setAttribute("type", "checkbox");
				stareCheck.checked = stares.has(resultId);
				stareCheck.addEventListener("change", (e) => {
					if (e.target.checked) {
						stares.add(resultId);
					} else {
						stares.delete(resultId);
					}
					saveFavorites();
					updateOrdering();
					});
				favDiv.appendChild(stareCheck);
				favDiv.appendChild(document.createTextNode("Staring"));
				
				// add image url
				var modifiedLibraryDiv = document.createElement("div");
				modifiedLibraryDiv.style = "display: flex; justify-content: space-between";
				var libraryAnchor = capDiv.lastChild;
				capDiv.appendChild(modifiedLibraryDiv);
				modifiedLibraryDiv.appendChild(libraryAnchor);
				var customLibraryDiv = document.createElement("div");
				customLibraryDiv.appendChild(createAcornizerIconElement(18));
				var libraryImageUrl = document.createElement("a");
				libraryImageUrl.href = `https://cdn.download.ams.birds.cornell.edu/api/v2/asset/${resultId}/2400`;
				libraryImageUrl.target = "_blank";
				libraryImageUrl.innerText = "Image Link";
				customLibraryDiv.appendChild(libraryImageUrl);
				modifiedLibraryDiv.appendChild(customLibraryDiv);
				
				// add average rating (query api)
				try {
					// for result item
					var modifiedRatingDiv = document.createElement("div");
					modifiedRatingDiv.style = "display: flex; justify-content: space-between";
					capDiv.insertBefore(modifiedRatingDiv, userDiv);
					var ratingAnchor = capDiv.getElementsByClassName("RatingStars")[0];
					modifiedRatingDiv.appendChild(ratingAnchor);
					var customRatingDiv = document.createElement("div");
					customRatingDiv.style = "display: flex";
					customRatingDiv.appendChild(createAcornizerIconElement(18));
					var avgRatingDiv = document.createElement("div");
					avgRatingDiv.id = `avg${resultId}`;
					avgRatingDiv.innerHTML = 'Avg: (loading...)';
					customRatingDiv.appendChild(avgRatingDiv);
					modifiedRatingDiv.appendChild(customRatingDiv);
					
					fetch(`https://media.ebird.org/internal/v1/get-rating/${resultId}`)
						.then(r => {
							if (r.ok) {
								return r.json();
							}
							throw new Error('rating query failed');
						})
						.then(data => {
							var ratingDivToUpdate = document.getElementById(`avg${resultId}`);
							var resultRatings = data[resultId];
							avgRatingTxt = 'Avg: ' + parseFloat(resultRatings.ratingAverage.toFixed(3)).toString();
							myRatingTxt = '';
							if ("myRating" in resultRatings && resultRatings.myRating > 0) {
								myRatingTxt = "My: " + resultRatings.myRating.toString();
							}
							ratingDivToUpdate.innerHTML = myRatingTxt + " | " + avgRatingTxt;
						})
						.catch(err => {
							console.error('rating query failed');
						});
				} catch (e) {
					// ignoring missing ratings, etc
				}
			}
		}
		cardOrder += 1;
	}
	return gotNewResult;
}

function acornSorted() {
	return results.sort(function(a, b) {
		if (settings.sortByFunny)
		{
			let aa = getFunnyRating(a);
			let ba = getFunnyRating(b);
			if (aa > ba)
				return -1;
			if (aa < ba)
				return 1;
		}
		if (settings.sortByStare)
		{
			let aa = getStareRating(a);
			let ba = getStareRating(b);
			if (aa > ba)
				return -1;
			if (aa < ba)
				return 1;
		}
		if (settings.sortByFavorites)
		{
			let aa = getAcornRating(a);
			let ba = getAcornRating(b);
			if (aa > ba)
				return -1;
			if (aa < ba)
				return 1;
		}
		if (settings.sortByAlternates)
		{
			let aa = getAlternateRating(a);
			let ba = getAlternateRating(b);
			if (aa > ba)
				return -1;
			if (aa < ba)
				return 1;
		}
		if (settings.sortByNumRatings)
		{
			let ar = getNumRatings(a);
			let br = getNumRatings(b);
			if (ar > br)
				return -1;
			if (ar < br)
				return 1;
		}
		let as = getOriginalOrder(a);
		let bs = getOriginalOrder(b);
		if (as < bs)
			return -1;
		if (as > bs)
			return 1;
		console.log("oops?");
		return 0;
	});
}

function applyOrdering(containerElem, orderedElems) {
	for (var elem of orderedElems.toReversed()) {
		containerElem.insertBefore(elem, containerElem.firstChild);
	}
}

function updateOrdering() {
	console.log("reordering");
	// rebuild results grid from saved results
	var resultsGrid = document.getElementsByClassName("ResultsGrid")[0];
	applyOrdering(resultsGrid, acornSorted());
}

function applyAcorns() {
	if (!readNewCards())
		return;
	
	console.log("# results: " + results.length);
	
	updateOrdering();
}

var resultsObserver = null;

function observeResults() {
	if (!resultsObserver) {
		resultsObserver = new MutationObserver(function(mutations) {
			mutations.forEach(function(mutation) {
				for (var addedNode of mutation.addedNodes) {
					applyAcorns();
					if (addedNode.type == "li") {
						applyAcorns();
					}
				}
			})
		});
		var resultsGrid = document.getElementsByClassName("ResultsGrid")[0];
		resultsObserver.observe(resultsGrid, { childList: true });
	}
}

function processSearchResults() {
	if (!isViewSupported())
		return;
	observeResults();
	applyAcorns();
	loadMoreResults();
}

function refreshView() {
	if (!isViewSupported())
		return;
	clearResults();
	processSearchResults();
	updateOrdering();
}

var wasViewSupported = isViewSupported();
function observePageChanges() {
	var pagination = document.getElementsByClassName("pagination")[0];
	var paginationObserver = new MutationObserver(function(mutations) {
			mutations.forEach(function(mutation) {
				for (var addedNode of mutation.addedNodes) {
					if (addedNode.type == "button") {
						if (!isViewSupported())
							return;
						loadMoreResults();
					}
				}
			})
		});
	paginationObserver.observe(pagination, { childList: true });
	
	var viewObserver = new MutationObserver(function(mutations) {
			if (wasViewSupported != isViewSupported())
			{
				console.log("view change");
				if (isViewSupported()) {
					refreshView();
				}
				addSettings();
			}
			wasViewSupported = isViewSupported();
		});
	viewObserver.observe(document, { childList: true, subtree: true });

	function observeFilterElement(element, observeAttributes = false) {
		//console.log("observing " + element.textContent);
		var filterSpanObserver = new MutationObserver(function (mutations) {
			console.log("filter change");
			clearResults();
			loadMoreResults();
		});
		filterSpanObserver.observe(element, { 
			characterData: true, attributes: observeAttributes, childList: false, subtree: true
		});
		filterSpanObservers.push(filterSpanObserver);
	}

	var activeFiltersDiv = document.getElementsByClassName("ActiveFilters")[0];
	var filterSpanObservers = [];
	var filterObserver = new MutationObserver(function(mutations) {
			console.log("resetting results");
			
			for (var mutation of mutations) {
				for (var addedNode of mutation.addedNodes) {
					for (var span of addedNode.getElementsByTagName("span")) {
						observeFilterElement(span);
					}
				}
			}
			
			clearResults();
			loadMoreResults();
		});
	filterObserver.observe(activeFiltersDiv, { childList: true, subtree: true });
	for (let span of activeFiltersDiv.getElementsByTagName("span")) {
		observeFilterElement(span);
	}

	var filtersDiv = document.getElementsByClassName("filters")[0];
	var currentSortDiv = filtersDiv.getElementsByClassName("filterSection--last")[0];
	for (let span of currentSortDiv.getElementsByTagName("span")) {
		observeFilterElement(span);
	}

	// update when switching media type (birds vs habitats etc)
	var tabsDiv = document.getElementsByClassName("tabs")[0];
	for (let button of tabsDiv.getElementsByTagName("button")) {
		observeFilterElement(button, true);
	}
}

function addSettings()
{
	var existingSettingsDiv = document.getElementById("settingsDiv");
	if (existingSettingsDiv)
		existingSettingsDiv.parentElement.removeChild(existingSettingsDiv);
	
	var resultsGrid = document.getElementsByClassName("ResultsGrid");
	if (resultsGrid.length == 0)
		return;
	resultsGrid = resultsGrid[0];
	
	var settingsDiv = document.createElement("div");
	settingsDiv.id = "settingsDiv";
	resultsGrid.parentElement.insertBefore(settingsDiv, resultsGrid);
	
	var maxResultsInput = document.createElement("input");
	maxResultsInput.setAttribute("type", "number");
	maxResultsInput.id = "maxResultsInput";
	maxResultsInput.min = 1;
	maxResultsInput.max = cMaxAutoLoad;
	maxResultsInput.value = settings.maxResults;
	maxResultsInput.addEventListener("change", (e) => {
		var input = document.getElementById("maxResultsInput");
		input.value = Math.min(input.max, Math.max(input.min, input.value));
		updateSettings().then(loadMoreResults);
	});
	
	settingsDiv.appendChild(createAcornizerIconElement(25));
	settingsDiv.appendChild(document.createTextNode("Auto-Load Results: "));
	settingsDiv.appendChild(maxResultsInput);
	
	settingsDiv.appendChild(document.createTextNode(" "));
	
	var favSortCheck = document.createElement("input");
	favSortCheck.id = "favSortCheck";
	favSortCheck.setAttribute("type", "checkbox");
	favSortCheck.checked = settings.sortByFavorites;
	favSortCheck.addEventListener("change", () => {
		updateSettings().then(updateOrdering);
		});
	settingsDiv.appendChild(document.createTextNode("Sort by "));
	settingsDiv.appendChild(favSortCheck);
	settingsDiv.appendChild(document.createTextNode(" Favorites"));
	
	var altSortCheck = document.createElement("input");
	altSortCheck.id = "altSortCheck";
	altSortCheck.setAttribute("type", "checkbox");
	altSortCheck.checked = settings.sortByAlternates;
	altSortCheck.addEventListener("change", () => {
		updateSettings().then(updateOrdering);
		});
	settingsDiv.appendChild(document.createTextNode(", then by "));
	settingsDiv.appendChild(altSortCheck);
	settingsDiv.appendChild(document.createTextNode(" Alternates"));
	
	var ratingCountSortCheck = document.createElement("input");
	ratingCountSortCheck.id = "numRatingsSortCheck";
	ratingCountSortCheck.setAttribute("type", "checkbox");
	ratingCountSortCheck.checked = settings.sortByNumRatings;
	ratingCountSortCheck.addEventListener("change", () => {
		updateSettings().then(updateOrdering);
		});
	settingsDiv.appendChild(document.createTextNode(", then by "));
	settingsDiv.appendChild(ratingCountSortCheck);
	settingsDiv.appendChild(document.createTextNode(" # of ratings"));
	
	settingsDiv.appendChild(document.createTextNode(". Show on top: "));
	
	var funnySortcheck = document.createElement("input");
	funnySortcheck.id = "funnySortCheck";
	funnySortcheck.setAttribute("type", "checkbox");
	funnySortcheck.checked = settings.sortByFunny;
	funnySortcheck.addEventListener("change", (e) => {
		if (e.target.checked) {
			document.getElementById("stareSortCheck").checked = false;
		}
		updateSettings().then(updateOrdering);
		});
	settingsDiv.appendChild(funnySortcheck);
	settingsDiv.appendChild(document.createTextNode(" Funny"));
	
	var stareSortCheck = document.createElement("input");
	stareSortCheck.id = "stareSortCheck";
	stareSortCheck.setAttribute("type", "checkbox");
	stareSortCheck.checked = settings.sortByStare;
	stareSortCheck.addEventListener("change", (e) => {
		if (e.target.checked) {
			document.getElementById("funnySortCheck").checked = false;
		}
		updateSettings().then(updateOrdering);
		});
	settingsDiv.appendChild(document.createTextNode(", or "));
	settingsDiv.appendChild(stareSortCheck);
	settingsDiv.appendChild(document.createTextNode(" Staring."));
}

async function updateSettings()
{
	await readSettings();
	settings.maxResults = document.getElementById("maxResultsInput").value;
	settings.sortByFavorites = document.getElementById("favSortCheck").checked;
	settings.sortByAlternates = document.getElementById("altSortCheck").checked;
	settings.sortByNumRatings = document.getElementById("numRatingsSortCheck").checked;
	settings.sortByFunny = document.getElementById("funnySortCheck").checked;
	settings.sortByStare = document.getElementById("stareSortCheck").checked;
	await saveSettings();
}

function acornize() {
	processSearchResults();
	observePageChanges();
	addSettings();
}

function displayRatingsOnAssetPage() {
	var assetId = window.location.href.split("/asset/")[1].split("/")[0];
	var ratingDiv = document.getElementsByClassName("Rating")[0];
	var customRatingDiv = document.createElement("div");
	customRatingDiv.appendChild(createAcornizerIconElement(20));
	customRatingDiv.style = "display: flex; justify-content: space-between; margin-right: 4rem;";
	var avgRatingDiv = document.createElement("div");
	avgRatingDiv.id = "avgRating";
	avgRatingDiv.innerHTML = 'Avg: (loading...)';
	customRatingDiv.appendChild(avgRatingDiv);
	ratingDiv.insertBefore(customRatingDiv, ratingDiv.firstChild);

	fetch(`https://macaulaylibrary.org/internal/v1/get-rating/${assetId}`)
		.then(r => {
			if (r.ok) {
				return r.json();
			}
			throw new Error('rating query failed');
		})
		.then(data => {
			var ratingDivToUpdate = document.getElementById("avgRating");
			var resultRatings = data[assetId];
			var avgText = 'None';
			if (resultRatings.ratingAverage > 0) {
				avgText = parseFloat(resultRatings.ratingAverage.toFixed(3)).toString();
			}
			ratingDivToUpdate.innerHTML = 'Avg: ' + avgText;
		})
		.catch(err => {
			console.error('rating query failed');
		});
}

window.onload = function() {
	if (window.location.href.includes("media.ebird.org/catalog")) {
    	readStorage().then(() => acornize());
	} else if (window.location.href.includes("macaulaylibrary.org/asset/")) {
		displayRatingsOnAssetPage();
	}
};