MutationObserver won't trigger in user script on attribute change - any ideas? - javascript

Ok so I have the following user script(tampermonkey):
// ==UserScript==
// #name Allow only multiples
// #namespace http://tampermonkey.net/
// #version 0.1
// #description observe and remove multiples
// #author You
// #match https://www.bet365.com/*
// #grant none
// ==/UserScript==
(async function loop() {
try{
const betsipframe = window.getBetslipFrame.bind(window)
const element = betsipframe().bsFrame.getElement().contentDocument.getElementsByClassName("betSlip")[0];
(new MutationObserver(mutations => console.log(mutations))).observe(element, {attributes: true,
attributeFilter: ["data-restrictedmultiples"]})
}
catch(error){console.log(error), setTimeout(loop,89)}
})()
It's basically looping until no error occurs (which means the host page has fully loaded) and then it creates an attribute observer. However the attribute observer never gets executed nevertheless the "data-restrictedmultiples" on the betslip changes.
I don't know can the page scripts have some anti-tamper measures. (I've searched MutationObserver inside them but have not found anything matching.)

Related

Tampermonkey script to create a button and select a file

I am pretty new in Tampermonkey Javascript and inherited below script to create a button and hoping to select a file upon click.
However, the import data button is not showing in https://test.com/*. I have tested alert("hi"); code in https://test.com/* and it is working fine. Can somebody help me with the solution? What is wrong with the code? Or is it me since I'm noob :) Thank you very much in advance.
// ==UserScript==
// #name Test Tampermonkey Script
// #version 0.1
// #description Test
// #author Me
// #match https://test.com/*
// #grant GM_xmlhttpRequest
// #grant GM_info
// ==/UserScript==
(function() {
'use strict';
function importData() {
let input = document.createElement('input');
input.type = 'file';
input.onchange = _ => {
// you can use this method to get file and perform respective operations
let files = Array.from(input.files);
console.log(files);
};
input.click();
}
})();

Multiple Context Menu options - Tampermonkey

I understand that we can create a context menu option/button with Tampermonkey using
// ==UserScript==
// #name Context Menu
// #namespace http://tampermonkey.net/
// #description Test
// #version 0.1
// #author author
// #include *
// #exclude file://*
// #grant GM_openInTab
// #grant GM_registerMenuCommand
// ==/UserScript==]
However, I wanted to create multiple context menu options using a single Tampermonkey script and create multiple functions to perform the task according to the menu option/button that user has clicked.
As mentioned in the comment, you can use GM_registerMenuCommand to open a pop-up and then put all the requirements in that pop-up.
AFA shortcut keys, here is an example of how to set it up. You can adjust it according to your needs.
document.addEventListener('keydown', keydown);
function keydown(e) {
if (e.altKey && e.key === 'j') { // ALT+j
e.preventDefault(); // prevent default action of key
// do something
}
}

How to check the time difference between state change of a webelement using Tampermonkey

I have a webelement with text "A". After sometime it will change to "B" based on a backend process. I want to write a tampermonkey script to check for the time difference between this state change and if it crosses some specific time say 30 mins then I need to trigger a desktop notification.
One glitch is for checking the state change I'm refreshing the page for every 5 minutes now. Does this cause any effect on my requirement ?
// ==UserScript==
// #name Test State Change
// #version 0.1
// #author Aravindh
// #include https://www.google.com
// #grant GM_notification
// #require http://code.jquery.com/jquery-1.12.4.min.js
// ==/UserScript==
setTimeout(function()
{
location.reload(true);
var runStatus = document.getElementById("id").textContent;
var expectedStatus = "running"
var status = runStatus.localeCompare(expectedStatus);
console.log(status);
if(status > -1)
{
GM_notification ( {title: 'foo', text: '42', timeout: 60000 } );
}
}, 600000)
I have never heard of Tampermonkey, so i don't know if that would affect it in some way, but this can be easily done in vanilla JavaSript:
First of, JavaScript is an Event-driven, language. Everything can be made to act and react to changes in the environment. So using setTimeout to see wether something has chaned is not the best approach.
Instead you install an event-listener or observer.
I can't really give too many details, as i'm a back-ender and not really familiar with the dom and there might be an easier solution. but in Essence:
// create a Mutation observer (google for details, you'll find better info than i coud give you)
const observer = new MutationObserver(([{addedNodes, removedNodes}]) => /*add some callback function here*/)
// observe the element
observer.observe(document.getElementByID('yourElement'), {childList: true, /* observe childListChanges */})
// add the timer for the max amount of time (eg. 30min)
const timeLimit = 1.8e6
let currentTimeout = setTimeout(onExpire, timeLimit)
// the callback when the timer expires
function onExpire () {
// do something
}
Now every time the cildList of that elemnt changes, your callback will be called.
A callback could look something like this:
function callBack (mutations) {
// `target` is the element, added/removedNodes is the observed change
for (const {target, addedNodes, removedNodes} of mutations) {
// check if the change you are looking for occured
if (/*desired change occured*/) {
// kill the old timeout
clearTimeout(currentTimeout /* the timeout from above */)
// start a new timeout
currentTimeout = setTimeout(onExpire, timeLimit/* same params as before */)
}
}
}

Greasemonkey Script Failing To Remove Element

A lot of this script is basically cut and paste from other people's scripts that are working for them, but I'm having a strange issue with either .remove or .removeChild failing to run. The script crashes out the userscript engine at this point.
// ==UserScript==
// #name Strip Gocomics Sidebar
// #version 1
// #grant none
// #include https://www.gocomics.com/*
// ==/UserScript==
window.addEventListener('load', setkillsidebar);
function setkillsidebar() {
var interval = Math.random() * 5000 + 1000;
setTimeout(killsidebar, interval);
}
function killsidebar() {
console.log("Start Session");
// const adSidebar = document.querySelectorAll('.gc-container-fluid .layout-2col-sidebar, .gc-page-header--hero .layout-2col-sidebar');
var adSidebar = document.getElementsByClassName('.gc-container-fluid .layout-2col-sidebar, .gc-page-header--hero .layout-2col-sidebar');
console.log("Got Elements " + adSidebar.length );
if (adSidebar) {
console.log("Found SideBar");
var myParent = adSidebar.parentNode;
console.log("Made Parent");
// myParent.remove();
adSidebar.parentNode.removeChild(adSidebar);
console.log("Stripped SideBar");
var interval = Math.random() * 5000 + 1000;
console.log("Timer Time " + interval );
setTimeout(killsidebar, interval);
console.log("Set Timer");
}
}
So with the addition of the console.log items, I get the following in the Firefox's Web Console:
Start Session
Got Elements
Found SideBar
Made Parent
And that's a wrap, I have a death at either the .remove or the .removeChild so either I am not doing something correctly, or I am having an issue with a security setting that is preventing me from deleting elements from webpages that nobody has told me about.
And for more interesting information, although the title of this post is Greasemonkey, this fails with Tampermonkey as well.
P.S. This is being used in addition to some Stylish CSS that permits me to have a bigger comic view on a small monitor. Doesn't matter if Stylish is running or not.
There are many problems with that userscript, but they mostly boil down to: You need to note the error messages in the console and google the functions that are causing them.
For example:
That's not how getElementsByClassName works.
querySelectorAll does not return a node.
parentNode and removeChild both act on a single node.
Also: the second setTimeout does not appear to be needed. And the load event listener is also (probably) superfluous.
Here is the script with those deficiencies corrected:
// ==UserScript==
// #name Gocomics, Strip Sidebar
// #match https://www.gocomics.com/*
// #version 2
// #grant none
// ==/UserScript==
var interval = Math.random () * 5000 + 1000;
setTimeout (killsidebar, interval);
function killsidebar () {
//-- querySelector() and querySelectorAll () are not the same.
var adSidebar = document.querySelector ('.gc-container-fluid .layout-2col-sidebar, .gc-page-header--hero .layout-2col-sidebar');
if (adSidebar) {
adSidebar.parentNode.removeChild (adSidebar);
}
}
Although, this script will probably perform better:
// ==UserScript==
// #name Gocomics, Strip Sidebar
// #match https://www.gocomics.com/*
// #version 2
// #require https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js
// #require https://gist.github.com/raw/2625891/waitForKeyElements.js
// #grant GM_addStyle
// #grant GM.getValue
// ==/UserScript==
//- The #grant directives are needed to restore the proper sandbox.
waitForKeyElements (
".gc-container-fluid .layout-2col-sidebar, .gc-page-header--hero .layout-2col-sidebar",
removeNode
);
function removeNode (jNode) {
jNode.remove ();
}
It uses waitForKeyElements -- which is faster and more robust that a straight setTimeout.

Why doesn't this Greasemonkey script work with this jQuery plugin?

I'm using NinjaKit in Safari (Same as Greasemonkey). The codes are like this
// ==UserScript==
// #name demo
// #namespace http://dailymed.nlm.nih.gov/
// #include http://dailymed.nlm.nih.gov/dailymed/*
// #require http://code.jquery.com/jquery-1.11.0.min.js
// #require http://johannburkard.de/resources/Johann/jquery.highlight-4.closure.js
// ==/UserScript==
$(document).ready(function () {
document.title = 'Hello!' + document.title;
alert("ZaiJian");
$("body p").highlight(["a"]);
});
When I visit this page, the alert can be displayed well, but the .highlight function which depends on jQuery.highlight and jQuery doesn't work. It says:
TypeError: 'undefined' is not a function (evaluating 'c.toUpperCase()')
And I find it quite hard to debug this.. Does anyone have ideas about it?
I believe that NinjaKit currently doesn't do #require. Here's an example I made, that works in Firefox/GreaseMonkey and not in Safari/Ninjakit:
// ==UserScript==
// #name DEBUG
// #include http://localhost/Library.html
// #require file:///Users/#######/Sites/hello_world.js
// #require http://localhost/~#######/hello_world.js // EITHER WAY
// ==/UserScript==
alert('activated');
hello_world();
# hello_world.js
function hello_world(){
alert('Hello World!');
}
Either as a "remote" address or a local file, it worked fine in GreaseMonkey and failed in Safari. It's hard to get the ins-and-outs of NinjaKit currently, in my experience.
You need to read relevant docs before using the jQuery plugin.
First,
Create an entry in your style sheet for the highlight class.
.highlight { background-color: yellow }
In Greasemonkey, the equivalent of that is GM_addStyle('.highlight { background-color: yellow }');.
Second,
To highlight all occurrances of “bla” (case insensitive) in all li elements, use the following code:
$('li').highlight('bla');
You should have left out the brackets, i.e. $("body p").highlight("a");.
Third, I don't think you need $(document).ready() as Greasemonkey scripts are, by default, executed upon DOMContentLoaded event.
Putting it all together:
// ==UserScript==
// #name demo
// #namespace http://dailymed.nlm.nih.gov/
// #include http://dailymed.nlm.nih.gov/dailymed/*
// #require http://code.jquery.com/jquery-1.11.0.min.js
// #require http://johannburkard.de/resources/Johann/jquery.highlight-4.closure.js
// #grant GM_addStyle
// ==/UserScript==
GM_addStyle('.highlight { background-color: yellow }');
document.title = 'Hello!' + document.title;
$("body p").highlight("a");

Categories

Resources