'Allow userscript function to be called from injected button then save with GM_saveValue
I have written a userscript for a particular webpage, and this script has some variables that I would like to be modifiable by the user, without them having to edit the script by hand such that the variables survive script updates.
Currently I am injecting a new <form>
into the existing settings page of the website with the appropriate inputs and a <button>
to trigger an injected function of which should run GM_saveValue
with a value extracted from the form.
The problem is that this script/function isn't able to access GM_saveValue
as that only exists in the scope of the TM script itself, hence I cannot actually save the settings. The rest of the code is fine, except this problem.
I have also tried defining the function inside of the userscript instead of injecting it in a <script>
tag, but this has much the same problem that the page itself is unaware of this function due to it being in TM's scope.
Is there a way to either make GM_setValue
accessible to the script that is injected into the page, or to make the button on the page able to access the function in the Userscript?
Option 1, inject a script tag:
let custom_settings_section = document.createElement('section');
let settings_script_tag = document.createElement('script');
settings_script_tag.text = `
function qol_saveCustomVariables() {
GM_setValue("custom_currency", document.querySelector('qol_custom_currency').value); // GM_setValue is unavailable in this scope.
document.querySelector('qol_save_success').style.display = "block";
}
`;
main_content.appendChild(settings_script_tag);
custom_settings_section.innerHTML = `
</script>
<h3>Ch4rl1e's QoL Settings</h3>
<form onsubmit="return false">
<p>Custom Currency Symbol: <input id="qol_custom_currency" type="string" name="qol_custom_currency" value=${custom_currency}></p>
<button onclick=qol_saveCustomVariables()>Save</button>
<p id="qol_save_success" class="alert alert-success" style="display: none;">Saved!</p>
</form>
`;
Option 2 define function in userscript:
let main_content = document.querySelector("#rightcolumn");
let custom_settings_section = document.createElement('section');
function qol_saveCustomVariables() { // the button injected into the page cannot "see" this function
GM_setValue("custom_currency", document.querySelector('qol_custom_currency').value);
document.querySelector('qol_save_success').style.display = "block";
}
custom_settings_section.innerHTML = `
<h3>Ch4rl1e's QoL Settings</h3>
<form onsubmit="return false">
<p>Custom Currency Symbol: <input id="qol_custom_currency" type="string" name="qol_custom_currency" value=${custom_currency}></p>
<button onclick=qol_saveCustomVariables()>Save</button>
<p id="qol_save_success" class="alert alert-success" style="display: none;">Saved!</p>
</form>
`
main_content.appendChild(custom_settings_section);
Solution 1:[1]
Solved
By creating the submit button "properly" (e.g. with document.createElement
) and then registering an eventListener for "click", and putting the relevant functionality inside of that, it works!
let main_content = document.querySelector("#rightcolumn");
let custom_settings_section = document.createElement('section');
custom_settings_section.innerHTML = `
<h3 id="qol">Ch4rl1e's QoL Settings</h3>
<form onsubmit="return false">
<p id="qol_save_success" class="alert alert-success" style="display: none;">Saved!</p>
<p>Custom Currency Symbol: <input id="qol_custom_currency" type="string" name="qol_custom_currency" value=${custom_currency}></p>
</form>
`;
var custom_settings_save_button = document.createElement('button');
custom_settings_save_button.class = "btn btn-primary";
custom_settings_save_button.innerHTML = "Save";
custom_settings_save_button.addEventListener("click", () => {
GM_setValue("custom_currency", document.querySelector('#qol_custom_currency').value);
document.querySelector('#qol_save_success').style.display = "block";
});
custom_settings_section.appendChild(custom_settings_save_button);
main_content.appendChild(custom_settings_section);
}
(I did also move the div
that reports a success message but it should be possible to insert the button between the form and said div, it's more work)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | ch4rl1e97 |