sheep.js is the first version of the little sheep watermark in the bottom right corner of the page. Try right-clicking or long pressing it! It was used for almost all web pages created from the beginning of this website (2016-09-13) to 2017-11-30, when sheep2.js was created.
In addition to creating a universal watermark, sheep.js provides a variety of features and utility functions that were intended to be usable by my web pages—in a way, it's the predecessor to Reform.
Clicking on the little sheep brings you to the home page.
The little sheep can be dragged (with touch support), and its new location is persistent until manually reset.
Right clicking twice on the little sheep opens the default browser context menu, inspired by YouTube's video player.
Support for a notification system. This was intended to be used for site-wide notifications that I want to display to all my website's visitors, though it ended up being annoying, and I didn't really use the feature on my web pages.
First-time users are presented with a cookie notice about the site using localStorage.
localStorage
In subsequent visits, there is a 20% chance users get an ad for UGWA.
Pressing the Konami Code adds glowing red eyes to the little sheep for the rest of the session. Clicking on it sends you to a jumpscare.
At some point, I was against ad blockers for no good reason, so there was also code to detect ad block, and redirect ad block users to a Google image search for "trypophobia." A Scratcher threatened to report me because of it, so I instead made it subtly blur the web page until 2019, when ad block detection code was removed "temporarily."
Right-clicking or long-pressing on the little sheep opens a context menu with various options:
go to index page — Sends the user to the home page; same as just clicking on the little sheep.
hide little sheep — Hides the little sheep for the rest of the session.
reset little sheep position — Resets the persistent custom little sheep location back to the bottom right corner.
see page description — Displays the page description in a notification. The description is the same as what displays on Discord in the website embed when you paste a link to the page.
eval.js — Launches the eval.js bookmarklet, which opens a basic JavaScript REPL for mobile and school Chromebook users to run JavaScript on the page.
view source code — This was added fairly recently in 2023. It sends the user to the corresponding HTML file page on GitHub.
site search — This was added fairly recently in 2024. Opens the same sitewide search dialog as on the home page.
sheep.css contains a CSS reset:
Changes the text selection highlight color to a nice aqua.
Makes form elements inherit the page font.
Hides focus outlines by default. Considering accessibility was not a major concern when I started programming for the web, it's likely that most sheep.js pages are not accessible.
The little sheep is a custom <sheepmenu> element, so it can be hidden by adding:
<sheepmenu>
sheepmenu { display: none; }
SHEEP
Only sheep.js needs to be added to the web page; the script loads sheep.css. The script tag should be inside the <body> tag so that document.body is available when it runs.
<body>
document.body
Because I used to develop my website locally by opening HTML files directly in the browser (under the file:// protocol), I had to use relative paths (e.g. ../../sheep.js) instead of an absolute path like /sheep.js.
file://
../../sheep.js
/sheep.js
<script src="../../sheep.js"></script>
window.cookie — An alias for the localStorage API, but wrapped in a try-catch so in some browsers' private modes, accessing window.cookie won't throw if localStorage is disabled.
window.cookie
try
catch
SHEEP.notify(message: string, link?: string): void — Creates a notification that appears in the bottom right corner. message is a string containing the HTML of the notification message, and link is an optional string that makes the notification link to the given URL. The notification dismisses itself in 3 seconds if link is specified; otherwise, it's persistent until the user dismisses it.
SHEEP.notify(message: string, link?: string): void
message
link
SHEEP.dismissed: Record<string, 0 | 1> — An object mapping notification IDs to either 0 or 1 (probably to minimize the localStorage size). Dismissed notification IDs are persistent and stored under the localStorage key dismissed.
SHEEP.dismissed: Record<string, 0 | 1>
dismissed
SHEEP.dismiss(notificationId: string): void — Marks notificationId as dismissed.
SHEEP.dismiss(notificationId: string): void
notificationId
SHEEP.undismiss(notificationId: string): void — Marks notificationId as not dismissed.
SHEEP.undismiss(notificationId: string): void
SHEEP.textwidth(elem: Element, text?: string): numberSHEEP.textwidth(text: string, font?: string): number — A utility function that measures the rendered width of the given string (or the given element's input value) using the specified font (or the font of the given element, or the font of the webpage if unspecified) by adding a temporary element to the page, measuring its rendered width, then removing it.
SHEEP.textwidth(elem: Element, text?: string): number
SHEEP.textwidth(text: string, font?: string): number
SHEEP.search(encoded: string): Record<string, string | number | boolean>SHEEP.search(params: Record<string, string | boolean>): string — A utility function that encodes/decodes a URL query string (including the ? at the beginning). When decoding, if the parameter value is parsed as a number if possible, the strings true and ✔ become true, and the strings false and ✖ become false.
SHEEP.search(encoded: string): Record<string, string | number | boolean>
SHEEP.search(params: Record<string, string | boolean>): string
?
true
✔
false
✖
SHEEP.ajax(url: string, callback: (response: string) => void, onError: (status: number) => void): void — A utility function inspired by jQuery's $.ajax. Non-200 status codes are considered errors.
SHEEP.ajax(url: string, callback: (response: string) => void, onError: (status: number) => void): void
$.ajax
SHEEP.draggable(elem: Element, xwise: boolean, ywise: boolean, options: { x?: number, y?: number, minx?: number, miny?: number, maxx?: number, maxy?: number, onchange?: (n: number, m?: number) => void, parentdrag?: boolean, min?: number, max?: number, fitparent?: boolean }): void enables dragging on the given element.
SHEEP.draggable(elem: Element, xwise: boolean, ywise: boolean, options: { x?: number, y?: number, minx?: number, miny?: number, maxx?: number, maxy?: number, onchange?: (n: number, m?: number) => void, parentdrag?: boolean, min?: number, max?: number, fitparent?: boolean }): void
xwise and ywise determine whether horizontal and vertical dragging are enabled.
xwise
ywise
options.min sets both options.minx and options.miny (likewise for options.max; I think this is for one-directional draggable stuff). The min and max set the pixel value bounds of the draggable element.
options.min
options.minx
options.miny
options.max
options.fitparent enables constraining the element to the bounds of its parent.
options.fitparent
options.parentdrag allows dragging to start anywhere in the parent element.
options.parentdrag
options.onchange is fired with the x and/or y values while dragging, depending on whether horizontal and/or vertical dragging are enabled.
options.onchange
This page has a demo with the options { fitparent: true, parentdrag: true }.
{ fitparent: true, parentdrag: true }
SHEEP.pixelratio(): number — Computes the device pixel ratio.
SHEEP.pixelratio(): number
SHEEP.menu: Record<string, () => void> — A registry of menu items for the little sheep context menu. The web page can add more entries to this registry to populate the menu items. This page has added "Test menu item" to the context menu.
SHEEP.menu: Record<string, () => void>