Playing a Sound Notification when Specific Text on Page Appears - javascript

I'm trying to figure out a way to play a sound notification whenever the phrase "2 credits" appears in the top right corner on a specific website at: https://www.submithub.com/. As it stands, that specific area of the site oscillates between "0 credits" and "2 credits" depending on if you've submitted to the site within the last few hours. Once you are able to submit again, the text changes to "2 credits."
I have also provided a screenshot of what I am talking about:
I have been using code primarily derived from the following StackOverflow thread: How can I have a Tampermonkey userscript play a sound when a specific word appears on a page?
Here is the code that I am working with:
// ==UserScript==
// #name SubmitHub Notification
// #include https://www.submithub.com/
// #grant none
// ==/UserScript==
/* eslint-disable no-multi-spaces */
//-- Set the watched terms using the awesome power of regex.
var watchRegx = /\b2 credits\b/i;
var alrtSound = new Audio ("data:audio/mp3;base64,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/XQ0F5IZ02SDoNlsXoeUtnOLbFEXPeZyydac5R4ySMgFRpZijAjMEkby8yvS9fsyJVr8bzaHFxIkF0O9NftowAAG2uAwICBf/96y9dX//f////tv7e/+/9W/b9vovRv//r/+1nnrkVMjMzVFIgmgHTwRdQIlAAyUDA5pbQ+V2HSjkOppxxr7OYFZdMwI9A0xjAbYgFQApwAAiFgGTFHBs6HHAs4sYN3CGhlg4GKSBhfQhAwCRMcZoXCkLmUQw2JlEvmlNNkqDmK5eeyLMkhNWWmbIoLdkGRQW7XuzKX+hbbdKr2UdmzXPrUgaVCgAAUC0UAADf//p//Tr////Sn////97//p/2////////uSZEwAA8VDVcViQAIyTXidoIgAW60vPvm9gABsgCODACAA///pbb89r0MikIjvGBqdRZ1ETgQAAAAAAAADhnMGRtyGYweHciRtAUcKNGGGgsPrDm7rAjBAgGLsJPmMhgqFFwVUzGQAyVyMGBDeZAGGJhxAb2jiVQZ8VmDQJEvGpRYFPTERBQUyUOL1DSuCQoaMDHhMlDkdDBwctGXoL5EIit1nLdV2gIcCCYcB1TszTtTe0+DjVmuSFsinTCVUGGs+aekMvGM3PjsPOSzGGX/k8itdaQuloUGu9ZjcFVuxavjjrs1jqzOSiP3pTupUqy6bpN3Zmr//VjjWZuig/v///8thqJz3////0s1dd/pU3/u6f////////+v2f//+XMfA6H/F1pN//hYSf/jzygAAYAAAImCEhz0feHViByqpZUsyg6zqBqru2XRcFL1IlLD5DUjhVONqVDYZyqGAhyqLqBdAIRxJEekhJ0sr1Wq2NBTqGoay0Yk891bf9rWrr+2/mvrX4tv1/9t+sF7aJQVBUGgaiUFn/lg5wad8SgqCo//7kmQ5D/OLLctnYeAAMMAYjeAIAIAAAaQAAAAgAAA0gAAABOt21ttt0CYKwoDQlBUFQVOlQViXxYGj3EQNA0e1A19YK1/EQNf/lf//5Y9wa//+CtVMQU1FMy45OS4zVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVU=");
//-- Customize this next for your page or get lazy and use "body".
var cntnrNode = document.querySelector ("#mainArea");
if (typeof cntnrNode === "undefined") console.error ("TM: Container node not found.");
else {
var wordObsrv = new MutationObserver (alertOnWord);
wordObsrv.observe (document.body, {childList: true, subtree: true} );
}
function alertOnWord (mutationRecords) {
mutationRecords.forEach (muttn => {
if (muttn.type === "childList" && typeof muttn.addedNodes === "object") {
muttn.addedNodes.forEach (newNode => {
/*-- Restrict the kinds of nodes watched for better performance
and/or to avoid false positives.
*/
if (newNode.nodeName === "DIV" || newNode.nodeName === "SPAN" || newNode.nodeName === "P") {
if (watchRegx.test (newNode.textContent) ) {
console.log ("Found new instance of target term!");
alrtSound.play ();
}
}
} );
}
} );
}
As it stands, I cannot get "2 credits" to make any notification sounds via Regex, such as shown below, but I have been able to get just "credits" to work:
var watchRegx = /\b2 credits\b/i;
Here is the HTML of the specific part of the page where "2 credits" lies on the site:
<span class="grey black-text lighten-2 credit-counter"><span class="remaining">2</span> credits</span>
The nature of the HTML indicates that this might not be as simple as using a Regex with "2 credits." Maybe there is an easy solution. Any and all advice would be wonderful. Thanks in advance.

I simply changed the RegEx code to var watchRegx = /2 credits/; A simple enough solution. Thanks for all the feedback

Here, we might want to separately capture our desired substrings then replace it:
.+?<span class="remaining">([0-9]+)?<\/span>(.+?)<\/span>
Our desired digits are in this capturing group:
([0-9]+)
and the second part is in this group:
(.+?)
Test
const regex = /.+?<span class="remaining">([0-9]+)?<\/span>(.+?)<\/span>/gm;
const str = `<span class="grey black-text lighten-2 credit-counter"><span class="remaining">2</span> credits</span>`;
const subst = `$1$2`;
// The substituted value will be contained in the result variable
const result = str.replace(regex, subst);
console.log(result);
DEMO

Related

Can't get values past array[0] to translate properly

Okay, to start with I should mention this is a very small personal project, and I've only have a handful of coding classes several years ago now. I can figure out a lot of the (very) basics, but have a hard time troubleshooting. I'm in a little bit over my head here, and need a dumbed down solution.
I'm trying to put together a VERY simple translator that takes in a word or sentence from the user via a text input box, puts each word of the string into an array, translates each word in order, then spits out each translated word in the order it was input. For example, typing "I like cats" would output "Ich mag Katze" in German.
I've got most of it, but I CAN'T get anything but the first array element to translate. It comes out like "Ich like cats".
I've used a loop, probably because I'm an amateur and don't know another way of doing this, and I'd rather not use any libraries or anything. This is a very small project I want to have a couple of friends utilize locally; and I know there has to be some very simple code that will just take a string, put it into an array, swap one word for another word, and then output the results, but I'm damned if I can make it work.
What I currently have is the closest I've gotten, but like I said, it doesn't work. I've jerry-rigged the loop and clearly that's the totally wrong approach, but I can't see the forest for the trees. If you can help me, please make it "Javascript for Babies" picture book levels of simple, I cannot stress enough how inexperienced I am. This is just supposed to be a fun little extra thing for my D&D group.
function checkForTranslation(input, outputDiv) {
var input = document.getElementById("inputTextField").value;
var outputDiv = document.getElementById("translationOutputDiv");
input = input.toLowerCase();
//puts user input into an array and then outputs it word by word
const myArray = input.split(" "); //added .split, thank you James, still otherwise broken
let output = "";
let translation = "";
for (let i = 0; i < myArray.length; i++) {
output += myArray[i]; //up to here, this works perfectly to put each word in the string into an array
//prints all words but doesnt translate the second onwards
translation += myArray[i];
if (output == "") {
//document.getElementById("print2").innerHTML = "Translation Here";
}
else if (output == "apple") {
translation = "x-ray";
}
else if (output == "banana") {
translation = "yak";
}
else {
translation = "???";
}
output += " "; //adds a space when displaying original user input
} // END FOR LOOP
document.getElementById("print").innerHTML = output; //this outputs the original user input to the screen
document.getElementById("print3").innerHTML = translation; //this should output the translated output to the screen
} // END FUNCTION CHECKFORTRANSLATION
What it looks like
P.S. I'm not worried about Best Practices here, this is supposed to be a quickie project that I can send to a couple friends and they can open the HTML doc, saved locally, in their browser when they want to mess around with it if they want their half-orc character to say "die by my hammer!" or something. If you have suggestions for making it neater great, but I'm not worried about a mess, no one is going to be reading this but me, and hopefully once it's fixed I'll never have to read it again either!
Since it is a manual simple translation, you should just create a "dictionary" and use it to get the translations.
var dictionary = {
"apple": "x-ray",
"banana": "yak"
}
function checkForTranslation() {
var input = document.getElementById("inputTextField").value.toLowerCase();
var words = input
.split(' ') // split string to words
.filter(function(word) { // remove empty words
return word.length > 0
});
var translatedWords = words.map(function(word) {
var wordTranslation = dictionary[word]; // get from dictionary
if (wordTranslation) {
return wordTranslation;
} else { // if word was not found in dictionary
return "???";
}
});
var translatedText = translatedWords.join(' ');
document.getElementById("translationOutputDiv").innerHTML = translatedText;
}
document.getElementById('translate').addEventListener('click', function() {
checkForTranslation();
});
<input type="text" id="inputTextField" />
<button id="translate">translate</button>
<br/>
<hr />
<div id="translationOutputDiv"></div>
Or if you want it a little more organized, you could use
const dictionary = {
"apple": "x-ray",
"banana": "yak"
}
function getTranslation(string) {
return string
.toLowerCase()
.split(' ')
.filter(word => word)
.map(word => dictionary[word] || '???')
.join(' ');
}
function translate(inputEl, outputEl) {
outputEl.innerHTML = getTranslation(inputEl.value);
}
document.querySelector('#translate').addEventListener('click', function() {
const input = document.querySelector('#inputTextField');
const output = document.querySelector('#translationOutputDiv');
translate(input, output);
});
<input type="text" id="inputTextField" />
<button id="translate">translate</button>
<br/>
<hr />
<div id="translationOutputDiv"></div>

Highlight Every Instance of String in <div> - Javascript

I have seen multiple posts on here finding and highlighting strings but none have worked as expected yet. Below is my script currently:
var str = 'word';
var divs= document.getElementsByClassName('strings');
for (var i = 0, len = divs.length; i < len; ++i) {
if(divs[i].innerHTML.indexOf(str) !== -1) {
// something
console.log('YES');
str.replace(/(\w+) (\w+)/, '<div class="strings">$1</div> <div class="strings">$2</div>');
}else{
console.log('NO');
}
}
HTML:
<div class="strings">word word words</div>
Ideally this would highlight every instance of the string in my div each time the js is run as a function.
The code you posted is on the right track and regex replace is convenient, but be very careful that, in addition to using the correct logic, you're not opening yourself up to XSS attacks or regex escaping problems by sanitizing your input field (although the XSS issue would be mainly problematic if the user supplies the target/source text).
Use the "gi" flags on the regex to make your search case-insensitive (I used a checkbox to toggle), and feel free to loop over multiple text areas you'd like to search when updating (I left it as one for simplicity). Add \b to the regex to enforce strict word boundaries (also toggleable in the below example). You can also use basically any element or styling on your highlighted element. <mark> seems most semantic.
Lastly, it's worth ensuring that the search term doesn't consist of an empty string, which would add a lot of garbage highlight tags between every character of the text.
const escapeHTML = html => {
const ta = document.createElement("textarea");
ta.textContent = html;
return ta.innerHTML;
};
const escapeRegex = s => s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
const highlight = (searchTerm, originalText, caseIns, boundaries) => {
const pattern = boundaries ? `(\\b${searchTerm}\\b)` : `(${searchTerm})`;
return searchTerm ? originalText.replace(
RegExp(pattern, "g" + (caseIns ? "i" : "")), "<mark>$1</mark>"
) : originalText;
};
const output = document.querySelector("#output");
const originalText = output.innerText;
let caseIns = false;
let boundaries = false;
let searchTerm = "";
document.querySelector("#ignore-case").addEventListener("change", e => {
caseIns = e.target.checked;
output.innerHTML = highlight(searchTerm, originalText, caseIns, boundaries);
});
document.querySelector("#word-boundaries").addEventListener("change", e => {
boundaries = e.target.checked;
output.innerHTML = highlight(searchTerm, originalText, caseIns, boundaries);
});
document.querySelector("input").addEventListener("keyup", e => {
searchTerm = escapeHTML(escapeRegex(e.target.value));
output.innerHTML = highlight(searchTerm, originalText, caseIns, boundaries);
});
div:first-child {
display: flex;
align-items: center;
margin-bottom: 1em;
}
span {
margin-left: 1em;
}
mark { /* add styling here */
border-radius: 2px;
}
<div>
<input placeholder="search term" />
<span>Ignore case? <input type="checkbox" id="ignore-case" /></span>
<span>Word boundaries? <input type="checkbox" id="word-boundaries" /></span>
</div>
<div id="output">Fourscore and seven years ago our fathers brought forth, on this continent, a new nation, conceived in liberty, and dedicated to the proposition that all men are created equal. Now we are engaged in a great civil war, testing whether that nation, or any nation so conceived, and so dedicated, can long endure. We are met on a great battle-field of that war. We have come to dedicate a portion of that field, as a final resting-place for those who here gave their lives, that that nation might live. It is altogether fitting and proper that we should do this. But, in a larger sense, we cannot dedicate, we cannot consecrate—we cannot hallow—this ground. The brave men, living and dead, who struggled here, have consecrated it far above our poor power to add or detract. The world will little note, nor long remember what we say here, but it can never forget what they did here. It is for us the living, rather, to be dedicated here to the unfinished work which they who fought here have thus far so nobly advanced. It is rather for us to be here dedicated to the great task remaining before us—that from these honored dead we take increased devotion to that cause for which they here gave the last full measure of devotion—that we here highly resolve that these dead shall not have died in vain—that this nation, under God, shall have a new birth of freedom, and that government of the people, by the people, for the people, shall not perish from the earth.</div>
You're using the replace() method on the needle and not on the hay stack. You want to find the str in the innerHTML attribute and then replace the innerHTML attribute with a copy that is surrounding the given str found with `' tags.
Because you're using a variable for the regex search you need to first make a regex object and inject the needle string into it. also give it the g flag so it matches every instance of the found regex:
var regex = new RegExp(`${str}`, ['g']);
Then you manipulate the innerHTML attribute of the div element:
divs[i].innerHTML = divs[i].innerHTML.replace(regex, `<span class"highlighted">${str}</span>`);
Now the script will look for the word and wrap it a span with .highlighted class.
So now all that's left to do is fix the css to handle it:
.highlighted {
background-color: yellow;
}

Firefox Extension is Preventing Javascript Running

I'm writing a simple Firefox web extension, which will replace certain words (e.g. acronyms) with expanded versions. My code is as follows:
var replacements = [];
replacements["example1"] = "My First Example";
replacements["example2"] = "Second Example";
if(!window.location.href.startsWith('https://ignore.thissite.com/')){
for(key in replacements){
replaceOnDocument(new RegExp('\\b'+key+'\\b', 'gi'), '{{{REPLACE_'+key+'}}}');
document.body.innerHTML = document.body.innerHTML.replace(new RegExp('{{{REPLACE_'+key+'}}}', 'g'), '<abbr title="'+key+'">'+replacements[key]+'</abbr>');
}
}
function replaceOnDocument(pattern, string){
Array.from(document.querySelectorAll("body, body *:not(script):not(noscript):not(style):not(code):not(pre)"))
.forEach(someNode => Array.from(someNode.childNodes)
.filter(childNode => childNode.nodeType == 3)
.forEach(textNode => textNode.textContent = textNode.textContent.replace(pattern, string)));
}
This seems to replace all the instances as expected, but I've noticed that Javascript doesn't seem to run correctly on pages that the script has run on. I've been staring at the code for half an hour now and can't work out why that would be the case. To make things worse, the problem seems to be intermittent (although happens more often than not).
Any ideas as to why my code would prevent Javascript running as expected?
I already speculated that replacing the content of body.innerHTML may cause issues, so how about using the following approach for replacing text? codepen example
const walker = document.createTreeWalker(
document.body,
NodeFilter.SHOW_TEXT,
{
// filter / exclude tags
acceptNode: function (node) {
return node.parentElement.nodeName === "SCRIPT" ? NodeFilter.FILTER_SKIP : NodeFilter.FILTER_ACCEPT;
}
}
);
while (walker.nextNode()) {
// replace every H with #
walker.currentNode.nodeValue = walker.currentNode.nodeValue.replace("H", "#");
}
This iterates over every text node excluding script text nodes and replaces their content.

Class should be shown/hidden, depending on its content - but it only gets hidden

I'm working on a PHP-chat right now.
When a user logs in he automatically sends a message "logged in" that is shown to everybody, when he logs out he automatically sends "logged out" that is shown to everybody (except him of course).
When all users logged out, all messages are deleted automatically.
I'm now working on a function that tells you, whether you are alone in the chatroom or not.
I want to solve this using JavaScript. The script I use right now counts how often the term "logged in" and the term "logged out" appears in the chat history (yeah, not the ultimate solution, but absolutely sufficient for my use)
Here's the code:
function countverlassen(){
var temp = document.body.innerText;
// the g in the regular expression says to search the whole string
// rather than just find the first occurrence
var countverlassen = (temp.match(/verlassen/g) || []).length +1;
console.log(countverlassen);
}
function countbetreten(){
var temp = document.body.innerText;
// the g in the regular expression says to search the whole string
// rather than just find the first occurrence
var countbetreten = (temp.match(/betreten/g) || []).length;
console.log(countbetreten);
if (countbetreten >= 2 && countbetreten != countverlassen){
$('.alleine').hide();
}
else if (countverlassen >= 2 && countbetreten == countverlassen) {
$('.alleine').show();
}
}
The class "alleine" only contains the text "You are alone in here right now".
When another user logs in this should be hidden, when all other users except you log out it should be displayed again.
Hiding the class works fine, but it just won't reapper again when everybody else logged out.
You can see it in action here: http://team3.digital-cultures.net/index.php#
Just pick a name and chosse a start / destination from the dropdown.
What am I doing wrong?
Thanks!
EDIT: For testing purposes you can just enter "betreten" ("logged in" in German) and "verlassen" ("logged out in German") in the chat, no need to log in with multiple accounts :)
You need to use return to get a value out. Using the function name is only creating a new local variable. I've renamed the var to make this clearer.
function countverlassen(){
var temp = document.body.innerText;
// the g in the regular expression says to search the whole string
// rather than just find the first occurrence
var verlassenCount = (temp.match(/verlassen/g) || []).length +1;
console.log(verlassenCount);
return verlassenCount;
}
Use countverlassen() to call the function and get the value. Store the value instead of calling the function every time.
function countbetreten() {
var temp = document.body.innerText;
// the g in the regular expression says to search the whole string
// rather than just find the first occurrence
var betretenCounter = (temp.match(/betreten/g) || []).length;
var verlassenCounter = countverlassen();
console.log(betretenCounter);
if (betretenCounter >= 2 && betretenCounter != verlassenCounter) {
$('.alleine').hide();
} else if (verlassenCounter >= 2 && betretenCounter == verlassenCounter) {
$('.alleine').show();
}
}

How do I make the quotations in this script clickable link?

I have this script from codelifter and it works great.
I would like that if the quotations below contained a url then it would become clickable.
Any help would be great.
Thanks
<script language="JavaScript">
// ==============================================
// Copyright 2004 by CodeLifter.com
// Free for all; but please leave in this header.
// ==============================================
var Quotation=new Array() // do not change this!
// Set up the quotations to be shown, below.
// To add more quotations, continue with the
// pattern, adding to the array. Remember
// to increment the Quotation[x] index!
Quotation[0] = "http://www.youtube.com/watch?v=zH6U5y086hw";
Quotation[1] = "Sanity is a golden apple with no shoelaces.";
Quotation[2] = "Repent! The end is coming, $9.95 at Amazon.";
Quotation[3] = "Honesty blurts where deception sneezes.";
Quotation[4] = "Pastry satisfies where art is unavailable.";
Quotation[5] = "Delete not, lest you, too, be deleted.";
Quotation[6] = "O! Youth! What a pain in the backside.";
Quotation[7] = "Wishes are like goldfish with propellors.";
Quotation[8] = "Love the river's \"beauty\", but live on a hill.";
Quotation[9] = "Invention is the mother of too many useless toys.";
// ======================================
// Do not change anything below this line
// ======================================
var Q = Quotation.length;
var whichQuotation=Math.round(Math.random()*(Q-1));
function showQuotation(){document.write(Quotation[whichQuotation]);}
showQuotation();
</script>
This is what I would do:
Assume quotation begins with http(s)://
In ShowQuotation: Use a regexp to identify such strings. Might be unnecessarily complicated. Check if a length-7 substring is http:// OR length-8 substring is https:// , assume the rest is all part of the URL
Make it a link
function showQuotation(){
if(Quotation[whichQuotation].substr(0,7)=='http://' || Quotation[whichQuotation].substr(0,8)=='https://')
document.write(''+Quotation[whichQuotation]+'');
else
document.write(Quotation[whichQuotation]);
}

Categories

Resources