Last active
September 22, 2021 16:16
-
-
Save derlin/50b02e293f8dda69eb46f25ad97c63d7 to your computer and use it in GitHub Desktop.
Get notified when something (pattern, text) appears on a page. Great for pages showing logs !
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } | |
function toArrayOfPatterns(searchPatterns) { | |
// transform strings, patterns, or arrays of strings/patterns into arrays of patterns | |
return (Array.isArray(searchPatterns) ? searchPatterns : [searchPatterns]) | |
.map((pattern) => typeof pattern == "string" ? new RegExp(pattern) : pattern); | |
} | |
async function isNotificationPermissionGranted() { | |
// ask for permission to show notification | |
return new Promise((resolve, _reject) => { | |
const permissionDenied = () => console.log( | |
"%cYou didn't grant notification permission for this page. Aborting.", | |
"font-weight: bold; color: red"); | |
if (Notification.permission === 'granted') { | |
resolve(true); | |
} else if (Notification.permission === 'default') { | |
console.log("Requesting notification permission."); | |
console.log( | |
"%cFROM FIREFOX 72 onwards%c\nIt is not possible to trigger the permission prompt without user interaction. " + | |
"A little icon should have appeared on the left of the URL bar though. Click on it to grant permission !\n" + | |
"See https://blog.mozilla.org/futurereleases/2019/11/04/restricting-notification-permission-prompts-in-firefox/", | |
"font-weight: bold; color: red", ""); | |
Notification.requestPermission().then(() => { | |
Notification.permission === 'granted' ? resolve(true) : resolve(false); | |
}); | |
} else { | |
permissionDenied(); | |
resolve(false); | |
} | |
}); | |
} | |
/** | |
* Wait for some text/pattern to appear on the page, and show a notification. | |
* The `searchPattern` can be a string, a pattern (`RegExp`), or an array of string/pattern. | |
* If an array is passed, the notification is shown as soon as any string/pattern is found (logical OR). | |
* | |
* @example | |
* waitForText([/hello.*worlds?/, "exact match"], document.getElementById("out"), {title: "My Title"}) | |
* | |
* @param {(string | RegExp | [(string|RegExp)])} searchPattern the pattern(s) to wait for for (logical OR) | |
* @param {HTMLElement} element in which element to search for the string (default: the whole body) | |
* @param {object} notificationParams notification param overrides (see https://developer.mozilla.org/en-US/docs/Web/API/notification) | |
*/ | |
async function waitForText(searchPattern, element, notificationParams) { | |
if (!await isNotificationPermissionGranted()) return; | |
const elt = element ?? document.body; | |
const patterns = toArrayOfPatterns(searchPattern); | |
console.log(`Waiting for any of ${patterns}.`, | |
"Type 'window.stopWaiting = true' on the developer console to stop the wait, or reload the page."); | |
while (!window.stopWaiting) { | |
console.log("..."); // show that something is working in the background | |
let matchingPattern = patterns.find(pattern => pattern.test(elt.innerHTML)); | |
if (matchingPattern) { | |
const match = matchingPattern.exec(elt.innerHTML)[0]; | |
console.log(`${match} found. Showing notification.`); | |
// compute actual notification parameters | |
let params = Object.assign({ | |
title: "Found!", | |
body: `found "${match}" in ${document.title}`, | |
requireInteraction: true // only dismiss on click (if supported) | |
}, notificationParams); | |
// show the notification | |
let notification = new Notification(params.title, params); | |
// switch automatically to the right window on notification click | |
notification.onclick = function () { | |
window.parent.parent.focus(); | |
notification.close(); | |
}; | |
return; | |
} | |
await sleep(5_000); | |
} | |
console.log("WaitForText aborted."); | |
window.stopWaiting = false; // reset | |
} | |
// this can be used anytime to stop the current waiting loop | |
window.stopWaiting = false; | |
// attach functions to window so they are available from bookmarklets | |
window.waitForText = waitForText; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
See the blog post https://dev.to/derlin/getting-notified-when-a-string-pattern-appears-on-a-webpage-318j for more information.