Custom tags and improved rating display for eBird media.
// ==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,iVBORw0KGgoAAAANSUhEUgAAAEwAAABMCAYAAADHl1ErAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAACxEAAAsRAX9kX5EAAC6fSURBVHhe7XwHlBzXdeWtqs65J/TknDCDQcYAIAiAIECQYCYlUSS1simJliwr2JItae1dWqaslS2tj9fZ0rFlWpaVaImyLIlZBAECBJHDIEzOM93TPZ1zrN77C8OcwOBzLB0/nD7Tobq66v737rv31y/gv+O/4z81pOW/v7Jx4eRp3cLFE+6ZuZnmfLFYl87lzKokjULWD/3PP/5aXmzzt1+9X/rU799f1r7wJvErC9ipk2dNocnzm70jgx/Mqvqr0vlkTa5YWlJl00lJZ/5rxaCcBooWE3SG377vj7zLX3vT+JUDbGp2zuodH9x2/tixj0V84Z2VjkqXrsIp601O2N1VH3RWOH3V1a5YPBpdZzbaJlUZi6lM5r3br9725eVdvGH8ygAWShX1iUXvVU/88MHfm7x4YavF7bS1rl4lrxgYwIbuPshGndgsxYfMxzBQ4LnrnXyu56OCDzMfUtI7B3tD8+vi8ksP2OhQTOpskhueePznn9//9LN3Oex11Vu37ZTWDKyFq9qyvNUrIwfEJ1AOzUKqWwuYapfffzFmR8fR0tP1Knx+qQELLaXkdHhqx6Gn9n311ER4/eZtm/XXXr8LdqNheYvXizDK4ydQSkWg69gE2Kr5nu3SR4xiNg6dyYFkJI7zgydwxc7dL+D0SwtYMRbQHTn89PsOPnvqT+zOjtZrbrxe6ultXP70jaPoPYNSyA+jww1YWZVGKx9GIJ9lpWZRKEvQV7RwS1YrwRs8fQprtl6tYfVLB1hZVSWfd8h95NCh3z70zOnf6u5Z77njrrtR4XkxQ9444shOT0CXiyIdCyG5FIXZVcGHC/lSESanGwZXDaAoKKZi0Bnt/FE9pIq6Xz7AyuWScXz4zM6TJ85+7ujRk1vtjgrLxz/xSdQ18ATfMJJAOs5sSSGxMA+7zYDo7DhGz5/F0nQQdk8Najo6EE5F0dnVCqOiIpPLQC3r4LZXUrIpUE0EtXOL9EsBWLnMIwc2hPxzn5oYHtr79P5nK8YmpuUP3/sxXHnVlZc2er0opTB15HGY9HoUUmlm1BJq3U48+fBPCYYdiUQC1ooKVDc1QTIoqHLbEPHPQy6m4DDpYDU7kMhm4G7tg3v7R/5rAzbvKysNtVjDp59BMX/d1PmzVQ/9+CH52MmzuP19d+Luez50SSS8ZhSQDcxi/uRJJGKzqHJWYuTcecT8QQLmRiSwBIvZiIKhAIPNAiPBszvssBokRJYC1Bg5KIUEisUys0sHe+MKFCwd//VK8gu/+2VpYOOVhq1X9W+vr3f9Lon3CjWTcBz8xWPyLx55DAFmSGNbF377878Pp0d0t1dGGfnIPApxcpTfC+/QBcxNTyEaCjFrishEI1DKKvRSGRarGYpVgd5ihtVth7PKDavVAlmWUCT5K4THbDJDsiioW7kJUtO1716G3btlV4VZyVnsXQORVVffml23sbPsqqmQaist4jdEHrzwt6hCjkcSSsC7YDx0aL9Lb1FaGprrmgK+eWc6mG3e2N+/NZ0Prdyy6zprKpbBIz98CIcPHUIhl4bVbsOWnbvx3g/dy129IvJpLAyfRqGUhiVfgG94CHNzUwjOBJCKE6hSHqVcEnJZWMgC9HodzFYrKmoq4ah2EjQnnNVVsFVUwmAywWA0w6g3QTYrgKsRUtXWdw7Yb61abR+o9fz6hoa6T5idHrfrjjvmqrdsnuPwpPmx4B7xEGqafRumS6/z+lzUazx59Ljz3LlBJ1nW2tTSoAsF/dL88LQkyxZZNrmwY/MVOH/xCE6dGILboEM2l4LZXYUP/sZvomcD9dMrYujgoyglgmio82Ds7CDCC14k0zF4L45AZcYYCJKs5giUyuwywmQ287kBDvKWo9IOi4slWVkJs6MCJocNFhs7pIEPSo5cVgdT1w1vH7Bvb1ipHzAoa63muc/ZraXrDWv32i0f+wrQ2Lm8xUuD2BWpcXQcqUwesxNjOHrwCTzy88cxM+uFy+NBc1s7/D4fD6yI9eu3Is/ymV3wsYxUbOypRooSYG4xTnJuwcd/7/Oobu5Y3vdyJAN46tGHsKG9BSPHTyIYDUNhBkW5j8j0OZQLGQJWglQuoLLSheqqSpRZetlSDtXMLpvdCL2JIFKbmWxuWCrd0NkdlBeXdJrUdouG1VsG7OubVuq3N2V726yhjzK1b1WySn1i0aCk1+5A5cd/E9mqemAxivjCHFLsUFV11SjIZaRzWbZnJloJGB+bxvd++DAeP3AC4XgS1W4rFNUAIwm3muXhrmpn2ZhRx2O984a18M57cXY4BF8sCE+DB1+4737UtfUtHxGjGMHo00/h1DNPwkFJcHZwCE0d3ah0mJDwTyEweoG8lIPTZtSIXlHITRY9bA4rDAp/W1emsi/TSjlI/i5mWB30ZidkkwF6Zlgkb0DFFfe+NcD+75Z+6cY6w4r2OvmTupT/tvxSsja+JCtBowun+Lmvsg5pjgblC7LlHNIS+YJcYTDrUd9cj4EtG+EhP0iqivm5BXz9mw/iiecuCPy0EGbGQktjNMnoaVmJq9avx7U72hEOBfDkwTF1Opway5dyP2xpqrvvf9zzAVx1w3u07xUjM5gcPM4OOIzJ8ycRmB4jOHrY3ZWocligJkNI+YehMpPMlA1OZo3JaILb7YKLA6Uiz7I0EUQdFDN1V20VTOyYRrOFMoMSI+tA7Z7ffQEn1sibx1N7+vW3dFk+WN8pf6OUmbtGiiaciahDPl1oxI8KRjwUjuFCvIBpbxTn/T6MR4PsZhGE4mn46ccmZxew6F+iYLTDYbMRhBCefuY5zAUpKJdDAFculdFUW4fdGwewa10LnOYs9h26qI748FS4UPgdtaz4pLL0vkq3Wb9+TSuHO4VFZs/UyAhOUj4EAz7qJpYW+Y5JBJVNQocidx7Xup7RqPBzSggCJssyrDYzStwH9wmLxQo7G4rRYoDEL5clGYmcgtq9970sqd4UsMlP3GJe3TT3GcUS+GM1GmvIhfRyMleL41IN/tWXxtEIO1Mig1g0jXAghMVwGEvhKFKJLJLFEpYI2CLfn5mZhc/nRW21B7Ii4/Dx0/CGXgRMRFNlFa7dvAVXr+lEhbOIaT/3P5aJRVXDew8cfvhsXV2zr1DM9VRXmldJ+Shsah7DJHfffACFArOZnFWgH7SwlBSJfMWsMupllIsFZpA4VZaeToZDELqVjFbOsiLS0PN4zMwuI8uUbYEQW5EqWNBw61dfVYFvCFjo6590VNeF/6A4f/H3pHDUXY7lEFH6cdDWi30pBSe9fsywK+VZh5FkDGm1wB8r8x+QK5eQymbJ8QXkmDnJXBnBxTA7XRIDA5swMb2AkalLE51Ca2zrXY2926/E5u4OuE0F5I0yHto3VRgP4iPxXPSwzzepzntnirV1Tcd1UmlPMRX3FONxmPUWTE0uIMXfz+dyCEeotyQVdlJBkcclADLpWF4keAGYwsySmUGlUhYp2iW1IGkDqDfpUVKMSBSNiBfdmArp8Z1HD31JO8CXxOsCVrp/T6uSOvf/1LHBD5dTObvebIM/WY19mTrsm87hMDvd0tI8gvzRPEfw+WhqaURfRyfqq2vgJqmmEmkU1EtMRcx4gDls3DyAbL6E4ZEZ5JgZezauxy07d6K/pR4WcopCsfjk6bHyM2e8f5qH/M0zZx7X5t5F1NZ2JFLp7DGTTn9bPBS0Li2ysxbzKGTJRQajVlYldkQry4/yE+lUimVog6yTYGCpgsJAx+ZT5jCJLirLOhpsB4qyg46TBF+qxHTCkF9M6558+OmD313+2RfiVcbi0Gf/j1IOHt2OXnxHVXx3SqmkRZcsIuWT8VyoEkdjBpz2T2LePwJfXkxgvhgdHe3obmmDx+lCY4UbVWzfa1avhMvy4kyCNxDF2NQsVvb3o5uG10WNs47btNfVwCarLJ8sW70B50dDTygW05cGzz1KPQJ0923X9/XucJw4tV9NpOUzC/74xxW9RY2nEkgkI1CZyUbuq5JlbSVPlkol7a+Nx7IUXmT5laAY9OQnHfnJSMBEmzGjyOxKlyg/MmYsxpmtQRXeRHkhreh+JH73lfGyDHv41+8x7P6A5yPl5/7uL5LeoX7DdFguL5SxMKfgJwkPnozoMZWOwscyDCezJOoXL7RY2eGu3LQaqzobqVALGFizCh1tPZQE49yqQC67xFclFWiorcDAurXsmEVEfIvYtXUbnCYFBYpMqDL3X8wemfR+8vjpfRPalxj1Ne02PZTc4tJUybc4rbor6jPZQlGqdDhWWxVZLxsM9H0iEYtwu5zMNr0GmNlsQoWD3ZfNQNLpKamsKDLLiooeiUIJeUM9MoYqLBZ08KVLlC4pZLMpdywcvGXvNTvu3//s8ZeV5QuAffu6PfLWhthHLd3er8qlbK1CJsh5Q8jMqXjGX8b+hIyRooE7TcLHLijmjl4arQ31uHbXLpw5NYifPrYfi74Errt+F4l+HsNjY4hnLpWtgFglMW/dshltzc3sYmXUV7gg5TMIeb08USvCeXl8fCH6lWnvWHZ1726p1tMsZSUpX5ZLJU9ds+xp6DCUJOVGWTJeK5UMJrvZ43JV2amtqKnIUaQw+kUJBf6mzJ/NM6tyZR0iqQL8sSxmfGH4QilcmFjAuDeB4Wk/zo3O8zFbHie3BoPxcq6gqizx8Htvvv7OJw88+w/awTOEbdFizzpPZe3q6O+k3FmX9WIU8lIcOl8R5FWMlA04FoxjQsxGgkLrtYLKXCcpaG5uR4Vrluq9GXnyVS6fRyQsXNKLMTzpwzMHDuG9t96E9av7oGTTyEdTWKBANTMrGupbVb2cEzYKg0NPldf0XiXpodpNdve6Cqvruh5PfX+FotvqMsiVJoNKf2lAbZ0F0UQMc/NTCEWWmMl5dm4OeCqpHYdKRksk00hnc3xdot9U+TpXzhbjRVVS0lZnRbihpXW6s7l12umwe//qnx6476tf/F89sqIsage9HC+0zfKpr15b9h79d8kcsahPHUNxPo1yCPCHdPhHEv03zs4huLzta4U4u2t2XIEtW69ALFVi5yEnzF/AE088Bh812ivjPXu24+P33oPAzCTlVApKQcUvHn4Cq9euQ8/mbZkHHj3892dnwj82Gp3WFk/tphWdHTc47JbVulzeZooloGeWK2oaOSQQyoQRYWMJhJc0S1QkF2YJWDweJTBFZhlPU1YIIjlS0qvpbD4Xz+R8lBODre3tB1b0rTxaUVk58fUHHggsH97rhgbYgY/eoGwayH7NtKL1M0gnFPXJn0FNZfkUODOu4M+GJTwWKwoJ+IYhdlbp1MNsdSCTY4fiiKdf6G8vhpGd6Z67b8Wt1+3B5IVBCHnQUtuAnzz072ivb0Rb5woYW3pyz16YTbZ3rDIXImlzwh+QzNkYu2wKeTXL9p+mCqexDi0iGA9DpfYysEumCL6eXkcql0vJOLdKJnOszIxOr4szqxZKZWnQaDI9vnFg8/HahrrIP3/7gefNxmWFBtjB96xp2fah6x/G9t6VWHgYhW/9GNlDJSS8ZTyoNOMbrOtRdpl3J2TcfMNN2LS2A97JSejoMdVUhnzWRE+n4MLpUyT/LJq7e0nMVhrwMB2ASjujiH7A7IEGVopyJF8oIk8zX+DgSDYdATOo/kBgke89q1f0+/KZ7LlSvuQ1mGyR6hpPxlPjKT6y79F3dCLSX914lfT+vXVfqL2x/4/Z/w1YOon0j34K+aiEhbCKfzcO4O+PXcRUgvX5pjn2xmGlwl67aj2u3rEdLfUuZGJxjA0O4uKZMzCZjOxOaQRYbotLMVRV0PxKBMFkgaexDhanGSHyqOhTKrurQkGqYyfMs8ziCZZ0sZwpldQndUbj/ZQO506cOfXODvZ1Qrm+u9G6whL5E8eqrha4XGwpUUimKNRgBlOZNnZHO07NzSFTejlxv9WoowG/7ZZbcMXmDWhvaUJZLSNMwI6ePoNnzg5h0h/CeCiOQIrGna00mM6Rf3Lo6utCa3sjaLqRyaZIRbQ3egnJRBw5Ookys0xRy3mb0/PDo2dP3ekL+Be9iz72yf+ckFN5OFOJVAOETJApMJfOoTgjrs01IVi1DoEkiUyTty/0h7cUEjtn/5rVuPH6G7C6fzVPvBkGo17rz9RRbCoxLW9f3RZwacbTaEEslsSCL0BVLtQ7aIUmMToyhuGhUf4dKQeWAmPZXP5PL33rPzdkVTE5TE67BQYKau8J4NERSEeXEFW7MaxYEKCUEFyh0yZN3xpoEr+zadNm7LxqJ3q7e6j83bBTNgiLovAhJvAy+devnEA8haefOYSjNOqnz17AocPHsW//EYzOhxBhM4mTjTI5Va1vaBk8curI0PLX3nH8yX3/63UvnctlteguqRkTh5ui5xGUySOGVg9CJSc5LIJETEVGeEXyyUtk22VFfWMD+letQk93N8GqgJmZVaZBF7MDTvrM9vZm7KAUsdA7vl6kKDemF4MYHJmGj24h86K50KKqvq18+PTpDyy/fMvx2U9/6tVZIKkrl5+9KmSDnHWX5YwCE0ndzWGzpAlSA8LVvSRhHX1WRFPnskQF/caTGy+E0Wwl73Rh/cYNaCBhGwmUXpGg0roolOGSMFX5HAxKEZs29uIPfv+TWNXfvfzttxI6VFR73h5XMD77qU8qKJe3LL98ISRJml9++qqQ7YaS01VplcthZnSgAFVxILdYjUWRTYoNKj2agT4xr2YInOaD3zhkPSqrPRpvtXe2wWKzQhXikTyoJ1lLFJUGMeVCAG0mmVlXpDPQ4ZYbd2FlT9vyTi4v7HYHqqsr3zZgf/G3f1fi6B1bfvlCEDAhCV4zlI+sa9y5ur6wV/H7FHU4ijJJNi6vxTQN6TkSq4/dKEufl9e45s07tdFiZyk2orO7i+a7QZsBNegkbSLPTBkgU8+VS9RQOYraTJR8Jq6NlGAyyNpV51QygihJvnQZaqmhuRGnThzVWtLua279fEd7z7n2tp7C5NSI9vnlxJFjx19R5MAvDhx81XvPh/Td2we+tLcl8L8t0pKiSMwgtwWL6Zvx82QHHty3D2emhhATkl8DS+aJO2Ckqo4nXs9FGLBp5zZcf91uNFQ7kE1nYNTp4LSaCYoATiJAKgcgxmaSgUKZICb8xIxpPB7DjHcRQ+PzCIWzCIQyiERz8FNyWCwWberG5eTvm/XMLD53uwishG//07dfN8vuev+v6Znd5e/94F/ffLQvI6Qv793557dXzX2ms8krw1GCsaEWocEGfCfYi387O4JBispk+dK8V3vLCpGvBCuOYEjMlr5yIJhF7mrc/p4b0NfdBpU8ZRXTK04rrOyKel0JOpk6imWJco7bU6HL5E1mmKoKo07LQ9WfL/EMYWVm69gFyaOZkmZ7ZCXPn1ch68R1wjICS3F4vRGa9iDSuULZarZkDHpjcv9TP9FWp9x554d+9OCD33qfeP5uhfTpvTd98X2m0T/aflVMhj0LyeNB4MkUvj7Tj3MlO04fO43JpTluWkB3Rz/a2loxSyE7NHL20h6WQzbYYbQ70dHZii3r++Bg46vhvmiY4bSZoCvnIda5CbAUmZxGsAosTUisPYKoslR1CnmzbEKxYIA3EEYgEofOaEWZfBcOh7C0FEIqm0OQQM3RMk0MzXJ7IXeEClgW1iY3Otvb0N/XW25tbS5bbaayVCzJyXi8+Jd//WevKxcuN5SNfb1St5J8b1tP0SizJEvZPCKLCp5ZtCJaMiPPUwuGo3T6OYQiQcoBN0fWT5MrbMrzIZHrmQF6USoV8LhsqHbbYbMosNJtGfTMRGaUmEcXmaQWxRRLBkXaGko8gsWMyespThMciEVcGPFifMoPH93G6IQPJ0+P4AQfpwdDOHc+jMnpMI+RNKEt6hHVKDJdVByfc9/hpQjGF3zS8OioNDo+JU9MTkiFYkEZHxvSJgM//YlPfPDY8eOD4vlbDenjN9xovt4a+f41G+Zv1hW9srAdwdgAvvicDmcCtCd6jrbfj0Xf6PJXAJu9gtYkvPzqlSGRW5xYQcJft64H3Z3t2lVlcdG7VMwye4S0oMrPpZHMcP88z0V/DLFEDgF/VMuqcCINP/1kUdWzrMnpOqaraAIE+AUWEFO34koQuzKNJV9zAAvCLwjghDMSD/6QbOQfvscDMFvMaKPFWrOyJ/r973/HzQ3ecmhk+cAtO264tXvmew7jglPmziciu/GV8xKeHp9BXUMLyuStY0f3ccvLaF3LUUlh2tfViM2bN8LmsPCXyD38NbEahjtELJnExaERZsscMzbB0zMgTGGa1+aueJJ6E/8KIIT2I2gCKE0GEogiX4hVDgIo8ZdNBezEyJEXaZ+0Bzs7WzG/L+aXeNxifyUCSkpobKzB2r7uQn1t9el/eOCbm8VeLze0Q1jT2RtuM6RvrHal68uqFed8DhwNs1xyFvQM9NPLxTC/wK5YvgwdthyZXAE+H3mHXnGK5TUx6WNW0Szpbex+Ma3EnjsyiJmFEIk+i2QqzZIVfGSneKanNfGhI9AEF1brpZPNiwdBYFlrQIj1GgWWJiUKMjy+QvQSUAJQswW2unrIbjeKAnSRcOJ0iV08mcZSNK7E09n6a67c+vE733P78E17rh5//OkDYqM3DA2wVe0d+YpCdm1zVWw93EZpaq4KwzzwlM6KarbyfU/vQz7Lg3oLGSZCHGMoEoMvEESG5yZU4qI/iENHTmJoeAw5rYReEpQsqKiAzsZqkQ0wm+2wOFzskPpLl/IKJHYBFgR/CqkjiF4MonhPq1k+CKRYzpRLIR9PktKysFN+VNfWwEHwhM1T01k6wQKW4ikpmynY2MS2pVOJ4Ttvu3H26UPPveFJaoAdm5gor2/vz6+0p25WzRHz6XMGTJjqEeFnUroIG39owR/QBOel2niroRCwDMHys7vNIZ1+jakiZx8qurpR3diBpoZWrOjuZbPQo7G+Bp0d7cTRDcnmguKqIkQs64LIGnFugrOeD3E64pKeaAZ8XuaxMgPz8RkklqaRCC6ipq4Obb0rkOLX8lmVv9eCD97zIeeu3btuCvh99VesW3nx4JHjTNXXDg0wEU+OTU7u7ehsWuGU1k4uScpIuR4eTz1SbPcVlAfz8wsUoUKPvfQALzcEyGL0XwNsgxvta27Htl03oY2ypa62Hhs3bERNVQUaaqtw/Z6rsWHdWqzkSTY0t8JTU4Mk+S8aY4YVWa5lcTzPH5PYP0GUCajGZSxxrZOKDLz028moD4H5GVTV1GPFihU8qjJmpydFIzK1tbVtOHjw8PUD69bEb79x7/iBZ597RQm8BDARbS19p3os5g1KWWnzGlqlPMl3MSk6WAqxeBwpQaps26954m8rdFi3ey923XgtVq3rQyY+q10ZVyQdWhqqcPvNe+gvW+Cm8BXrJkpqmhSWRGWVC2M8ySI9KUUaz4JcR8ly6bj4EKK4zM9MVn5kR7lAEBUjVvT1sUcoSKciSIa9iAZDdB961FZXwmIysYfopY7uFVVmh2sPlYFt64a1F37trjtSjz751Asn/DLADoxOJXua28dXN7fuGc2UXfO5EtIk2kVy0BzFqo1GOqeV09vJsleHy9ODLZt3wW6uRG1VJeSiTEAonqU8dmxdj+3rWlFpN2hXe2Zn55Ah9xR58laLgyrBgIb6ZvAQmVMySgIgMeGvTUWK8xNNIa/1DAo/SHoFNrNZe4jlAzY2FuE6fPMT8M556WETqKLdMhiNaG5tNtht9s2xWGKvMG533HbzzCNPUM0zXgaYiJ9fmJnfuarPEJRTV04tZfSxJIVsnDxAkhQeMi1mYLU1ou80dNRnjehp7sanP/oBXLF1BRIZPyR6yx3brsC2Lf0wiZNllNksvF4fLVmUUiuLxSUfrtl9FTPPDEXNIsUyiyY4iFZ2WCFLtDJd5rciz1NkXDGDaCSEkJjhJZAVlRXYeuUVqKlpYjLM0kUsIRQMYGx0CHoCabc7ZJe7tmbtuvXXtba0Xt/T1qz8Yv+BY68CTMQPTlx4tqtz7a5EJtcazyQkxWCiHDAiGo1BbzCgkH2pyn+7YUBdcz8+dO+Hce3uXpw5vg/Hnz6ITEKFs8JCenDCImQFw2RQyFkxTI7PYWxkGDH62Ov37sTjjzyMQCBAkPVwVdailT44FgsuH59AW8gUhfx4C7bvvBbjEzNUI0Xc/b4PwGSidDp2BqnQAkz0cRY7vSt5MRNOIJ0tYO3mDVi/ZT0qq2tlm6Oq5vY7brtRHMtrAiZiQ++qQyarrTdXLLSJRUJiQisWI49xlC618udjOQ3ealgasWrNOmy/egssljJ+8eQjODM4SK7M4JprdmEFCf6lEac8OfjcEYzNzmBkYgInz47CYHGxTPNYuXIVdu7Yib6eLkyPjWqi2Gh3k7PWMYPakEwncced70c7ffDE2Bh9aQT3/eEX0dzRivPnh1FbWY3u1k64qxpQWdvMUq+nBs2x7BUYmShiiednf+cz9//d3//Nl14XsJMXz0cI2v6iimb6pZ5wNCaHxVVlkjJYBi/G2wGsBq19O9HY0kBDXsbSoh8P//wXsDg92LBhM3bt2AarWWTHi7E4P0+wFjBHU16UrBTGEiorPUgnEjCR/NevXQe33YYwy2qeJaZQkmwa2IJbb7kNmUwaCVLJmjVrEaS0mZ2eptqvw6YtmzSdF5jxYmDtJvStWgMHG4C4DhqPsDEk4nxehN1mhk4v4/Of+/z9rwuYiDU9vQmW4P58UV0fiyfaC6WCJO7BEXxw+fFKQC1o6t6N9Zu3YNPmfvKQCeMjk2ho7MGuPTdSWrSjqckDk1g5yK19Xi/5xE4QZnBueIpcVUB9XRslD0FvqqXYjyASmEcvdZvVZEQmGaflusAmUEYXdd32K7fDabPg3LlzSLHTx8JhlmwWS34fVq/pR1WVkxy2BD8HQpIKBL4btdRq8VgSU+NjrKoQajwVzNQqKhXd65ekiDPDFzCwZm2GNuf8Uji0N53LudJhMXEoCFUA8WbZJTjopVJGhqdjJ379nnvx4Q9fh/6VjRgePgULO9Ndd9/JknDScOfZsUKoq6qCVKb/ZPkbjArODl7E8ZMXUeGqxuYNA2hv9jCjgMmR0xi5MIhVq9ajqsKldb4zZ09rSwZ6umn+Ozq0DPT5fDh7+izi5GE1z6ZF0RsO+ykpHHBWN6ChtRUXBo8gvDiB/lX9aGpuo8TJazdG5PJpAlvJjK5+Y8BEnDo/iHX9a5ayxXxabzbvXvItsFYEYC8NARyPXgPo+XIVuxb3Mryko+qqsW33rfjD++7FmnYXZngwgcUA7r7rDngIltc3SSPug3dhFiva6zHJ33ZYFYyOnseDDz6M4bEZ7L1uL5pqK2GU0/B7x3D08GH4fTF0ruhCS3M9PX6JjcCPhYV59FN3VRN4vVFGhlSiMxjR0d7BAUmis6udZZ2m9oujs7sDPX2dBKkJ+/cdYFPxczB7KJRbLi0FpT91u1yw0dO+KWAizg+fL3e0d4+kctmmcDKxrizMrda6nw9iqKsibga+LzJKfObiQ2g2zfVq0dp7Be7+wF0Y2FCFZx49gOPHhrFh/Q70d9UiR7N+9swpHCGxL1KJx/3z+NmD38PM6AVcGBrGyTMTuPq667Hn2l2QKFITsXkMXTyNo0fPUiJ0sYH0aO6gRK/oZTYteBc0cIQgzbPU7OKOtZo68th6arpp2CmG33/XnUjHc+SrGTYeHZyeFrS29+P04Se0Uu9bvwnt7a38zEypIZNvDWLe5M3j3rs/aLZbTCmLzvDnXe29/qZ2MVVtXf5UBO2HmGoRd048PwaKAO0l5ehqQtfaAazqqMPBnzyKnz3+GFSa6/6BDlq+DMbOnMPYWADBUAYL83F88/tP4eDFeQTyRhT0dXA3rsTWga3wOLnX4jRCYR+mZyLMEr3WaT3UVT7/AryBWfrWJFyOCpZSEWlqrlMnjsLEqljV3oTGKis62+oxePYE6murccXO7bBXim45jaFTR6nrojzODTg1uoBjzz2nLU9f2duLblozs/kyAaPQa3NRpyhSeaTS7fxOT3e36qysXP5UBMGhGje4RVaJWWCCSVvy0qiuacBdd9yMZCqOJ54+gcmFGNpbOHrEeXrWi/1CMkyOwLfgxdTEIqamI+SdIk6fmYPZ6MRtN16nLb1cWvTSDyaRSmQwMz2nXQyppecUc21xlpdY3h4ILKGVnOR0OLSsiIRjiIRC2i0zTodFs1qiLOPUXZ7qCmzetBFdnW2am5lnN66sqEZfbx/Fsld7L0QZIiRGTa3n8gD7lx/+20WOoHz02DNFqVz6RjGfm2pofOn91QSMaXspt2RYaltgcon/2eD5sGBFZy+q3FYcOXoUE8ygNQM7sLZ/BeYn53BKXGwZm8bcvBdBClG/P0hAirDYGtHeuQ5XbtuO3VdtQCETxOzUGJ1OGdl0kXIhy5Jpgcttg9FogE6n04RsMBSkbGjUFinXejyoqazR7mNKJ9kJy1m6hQx0koyF2XkqzBIq+P3+lb3YROCcTifBbgcVPvr7+2EWd7XRb85xINLJ9OUBJqKYy6ofu+c3JKtRP5VKxL7FVC1J5udBMcJZ46EwbEfXls1o7+7kjl/wq9A5q7Fh3ToseWcxPDKG1hWrse3qKygfHFTvY5j1huFdiiMSyVDpKzDoKmh9duHLX/kcfuOTd2DTFd3UROMsrWe0ex+hKsyaKE/UxU7YzrHSa2tbDTo99VaKgJRYPmY4SBEW/l3R04tFH7OF3FUoZpHPprUV19NT09r1BZk8q6M4bWtpRmd7OztiFSrIeQ0NDZQw9drrmpoaDA8NXT5gf/3P/1T+h3/5ZvnxJ39eQqnwzWQsetSgp+oUYXaQdNdScF6F7q5OmCz0nP7nl4ZKqPDU88Q6qX38kI1WtHZ0shxrkKeem/MuYikYR5bK2mp1UrgO4L77PoX337GF3DaBtnYaflqd00eGSc4UoIk0wtE4eSqPVatXagJUouYSN4bqxfp7PpeZacJ/FkslZp1CjVdP32rHxOQU5UaWyj+tZZK4DprPUlOWS/TpOS1LnU47DDTqdpu4lcZOalZI+DqtS9aIu1iWz+otRa2nyq+WCp92OGwL4rXBU4v1A5u0G5/SqSRHW3TGZemhq0VzWyeqqHfE2knFaIfdZUMzxeC8149YRsXMPHdD4q+osGPHnm7MLT6BR3/6A9xw1R0w62qQisnsogl4yV9nzw3jwX97iN7RTeHZx/czSMaTBI3NgNLBarWR02oJGP+JiybMHrvdopVYOBKnZPGTvzLo7OyEw2XXthFLGUTZZTMpLbNMRr12qUDMXIjIU7cVC0UK2Jq3B9jPHvmPclNjw6CaL3xTNlaUmls6sX7dBo5oASW1yFQXZSP0l4SmlRuxe+9ejpiF/kxl9tmpd+phZ2/wLQYRICGLa46lQprfzeAH330cE8NF/MEX/pBAzHE/GUzPncfw+BACoSh95AybwwwMVPWxeBRZZoiqEhxmViIh5sqqWEpNzDaDVnbiHiOVAlg0ANHBR8cnNT2WpRhtb2uBnhkkQBPzYuIWIInIiywT2SZCfF9kaZbuIMcsfFuA3bT3VunZQ/uK9Z6qHzR3NQbbappQIRadSBnk02K9fZAnSgFrqUVTVy/qPZXIMv2zeQkecp3RkEeSfWJpKcZyE8sFdEilJfKLpB3UwJYBJIpxGmgZc5NjWJwJwOVsgD+cY3cNiP90SCvloeFJnqSYH7MQNLH8oETj3EiBadMWqlgpNA3skkpJgoPHJ+7xDkeiKHA7o0FBc2O1tvxKcJjgXHGjlo370rOkhX80GsS7JST5vpnfFdPsbwuwnz/2Hxp3dXV2zXQ3t56pYomJzmO2mRBPRFCk/xJhdZA8OVqd7GRi5HRMdTEZGI9nOdILLMkAuasIF/khk8potiVGWzS1MIp5/wwOH38W49NjKLGTtXS08fs6bT2FmMvK5wva1SzBXUKBFwsF2LQ7P8yavCgWxTpYMT3NPOdZCkDF7TTiRixRaoLvxOc6NgqiwuMqadcaJIKnp5Uyahlq4sOsZbBYpGXlILwtwJ6PH//kB9lqu+t7Jh2ySwGvlt4GvoB284NEveNBQ10NmuprkaC3S9GKiNIRGmpiep4lTFBZoqUiNRxLQJyQAPCppw7huefOUlyOavddqqrEkiigoqpau4ghRqvEL2dS4gTZo3nyAiABlgAmw/IRIUpN/J44FjF3L8pKo4mmRj6atP2IZaDEQ9vOQZIXWxbJWQqFnShLsVjZZLZo24oZkHcEmIhcMv1YLhWdDtL9JykExeITbcjgYHq70dbaxB818MTDSBOwHTu28pglxEm8eqMF7TTHKXHiTIOcuAxO1zA/F8Kh/cexqn8D1XgNd0crFA9yG1Wb28pSfwUpRJeCIYrPuEBmGRjKHxJ4JpPRXovMEEpdTFOLwRCflcR0DTtkZ1eX1gG1dbMERwBeV1er6bN0gvvkdgr3YSJoVotJGwhBHe8YsB89/KNALBr+GkWrGg/H2SUvXUIzOmpRxZP11FRoE48l+szulSspMdz0gXFtVAWhLvoW2fItLMUEwgl2woAPS6FF7D94AGcGT/P9IKIJP8t3AkGxpoNlmC/kEQ6GEWMJT07TJkXZNFhSefKf2KfIPgFAgb5S4CjKTtzyJ/4XAXHLn/hM/I8oIttyLG2t5AiImOvP0WiLBTP5bErjNz0H18ws05qAGADt7N5hPPzT738rn8yE1KyKqXFxA5oOwm/WNNWjzB+fnJpFT88qbN2+ncZ3SrufURYrdkp5RMV8E0WhKCNxm4veYkVB0pHMZXzpK3+Jr/35N/CPDzyEH/74AEZHpwhakIqb4pRlLO7DTDAbxKIWsQQ9Hk8sl3X2EmAsLbHuTGS8cAGVtHOCu8RzYXvEdiWRndxCiF5xASZEWyWyPRoJa/8hiFgPIlZMWshn4mbVdwUwEfFodCnPbpJMkCestahgdtU2MsUVg5byrST+Yi7PdE9SeIYQDAa0dWbi5q0AQSiVVJazlQK3D/WNHawtGflUHocOnMSzh87g4tgiZueo2/j92TkfIsyuAkt4kVZIhMvtYJYQwHhK40SxPwFIJBLh7yRJ6Blt0lHcdy6ag7ioMr+wwAwkZ3GgBGhG0smpMye5bULTdyXKJMFnojypZbXu+a4Btuibf1iSCmVZ0sPC7lhPsJpbGlFk1lW4nOQxFXPj44guRdnt2E3ZycKRGIJ8COXucDhh1Bkgl8qodruZpOLQnp934+kUogQ8hiLFZSwUYNOYgdfnxwIzJcbyqqp2EbAilgJhDpKJ5VSm0U+yZKeo36j3gkGt69XU1GorGUWZPnvoWa2MBWjiBlTRNELUhHPeGWo1WdOU6TRdRSqOsrgXk9u9a4B991t/8QW71RoUSyrFRYMaTzXTX+EBZSkmK/k3j2me5BKzyWyxaRc7xLXEmtoGqvANcDhdSJDQR8dGtZGmgFres1DrYppIlJYAUDQGPs8xk/gIkctmZ+aYOUKYQru6pKl2Wi0x6youoY2Pj7I5EHBymo0ZZqZUaKPvHR0Zx+Kin0zGxiD4iaUouufs3DzLUvTfSzfVi5v7BahlgvquAdbVu1UxmkzPVLP1V9FeuFwOjqiitWrxv5CIli6u/ZkIRh0N7RIzLUOpoDOY0NPXR9vjo3FOIjA/i5OnTtFzmrlXMf+xPL/2qrh0wbZA/pqjtRID4iToYtpGELtYoqUwi7L0nKe5P7H0XTQDsV5DbNvY0MLBqsWFi0MsvxxBo6Ag/7W1dZC/EuzAYv0bHQAJvyQuCAth8m4CNjZ0uJRNpf6ms6MtLWyQmBaJRyMcqbJ2EVh0yiqCaSJPLZA/NNLmQ9ykfuHCRSpzpyYHRCcqsUxVIRe0uzBffvXo5UEfyJMXV8XF2lgx5y5Mtct16X9pEoa7trZeA1FkthgssX+RTSYeX0d7O4+tSGsW1rpkiY1CLD4WxzIyfOlynEouFP6yRJ8qQcX/B5PFrMZ6IiYmAAAAAElFTkSuQmCC
// @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();
}
};