This one has always boggled my mind and I've been scouting for StackOverflow questions about dealing with the anonymous scope in userscripts for many years, never satisfied with the sidestepping workarounds proposed instead in most answers.
So there is a script on a page that assigns a callback to a DOM element's onblur
event.
To clarify, just in case, the callback is not assigned with inline HTML.
I want that callback to never fire. I can't disable the event (can I?), but theoretically I can unset a callback function from it.
Naturally I get that element in console and check its .onblur
property — I get null
.
Well, I'd love to believe that... but there is in fact a callback and it still triggers every time the element is blurred.
If I assign my own callback to that event — then both the "hidden" one and my callback get triggered.
The page in question is any random FANDOM/Wikia page with their new Oasis layout, e.g. Fandom Developers Wiki.
When I prettify this script from the page in Waterfox (a conservative Firefox fork), these lines catch my "eye":
6963:$(function($) {
6964: 'use strict';
6965: var $globalNav = $('.wds-global-navigation'),
6966: $searchContainer =
6967: $globalNav.find('.wds-global-navigation__search-container'),
6968: $searchInput = $globalNav.find('.wds-global-navigation__search-input'),
6969: $searchSubmit = $globalNav.find('.wds-global-navigation__search-submit'),
6970: $searchToggle = $globalNav.find('.wds-global-navigation__search-toggle'),
6971: activeSearchClass = 'wds-search-is-active';
6972: function activateSearch() {
6973: if (!$globalNav.hasClass(activeSearchClass)) {
6974: $globalNav.addClass(activeSearchClass);
6975: $searchInput.focus();
6976: }
6977: }
6978: function deactivateSearch() {
6979: $searchSubmit.prop('disabled', true);
6980: $searchInput.val('');
6981: $globalNav.removeClass(activeSearchClass);
6982: $searchContainer.removeClass('wds-search-is-focused');
6983: }
6984: $searchInput.on('input', function() {
6985: var textLength = this.value.length;
6986: if (textLength > 0 && $searchSubmit.prop('disabled')) {
6987: $searchSubmit.prop('disabled', false);
6988: } else if (textLength === 0) {
6989: $searchSubmit.prop('disabled', true);
6990: }
6991: });
6992: $searchInput.on('keydown', function(event) {
6993: if (event.which === 27) {
6994: deactivateSearch();
6995: $searchInput.blur();
6996: }
6997: }).on('blur', function() {
6998: if (!this.value.length) {
6999: deactivateSearch();
7000: }
7001: })[…]
I work with ViolentMonkey in Waterfox. (Should be roughly equivalent to GreaseMonkey in Firefox)
I don't know much of jQuery (which that code smells of to me) and never seemed to really need it in tinkering, but let me know if I'm missing something obvious.
To summarize in more specifics (wait, what now?):
I'm trying to unset a callback from document.getElementsByClassName('wds-global-navigation__search-input')[0].onblur
on e.g. Fandom Developers Wiki to make the search field remain on screen at all times instead of only appearing after you click on the search button (easily simulated with document.getElementsByClassName('wds-global-navigation__search-toggle')[0].click()
) but until the field loses focus (that's the hard part to neuter).
It's so jarring when I open the code on a page in a debugger, immediately see what needs changing in the script or in the memory after the script ran but have no ability to affect either.
I guess I could go @run-at document-start
and document.onbeforescriptexecute = funcRef;
to highjack the whole script and try dissecting it, but aren't there less drastic approaches?
P.S.
I couldn't create a "violentmonkey" tag to mark my question. Sorry, it's all about reputation.
Decided not to use the "greasemonkey" one, since it's outdated and grew its own slew of quirks.
From a practical standpoint, I'll still appreciate a simple special-case solution to keep that search field constantly open, but I'd like the focus to be on the general case of the question since I tend to run into this problem of altering data in the anonymous scope pretty often.
What are the ways of accessing the values in the anonymous scope from a userscript, like that "hidden" callback value of the onblur
event that I don't seem to be able to change?