I'm writing a Chrome extension for Facebook and want to programmatically trigger the submission of the focused comment draft on a post. The default behavior is to submit when the user hits the Enter key, so I'm attempting to trick the Facebook UI into thinking that the user did so.
Facebook uses React and a contenteditable div for comment forms.
Here's a set of things that I've tried:
1) jQuery Event triggering $('<the contenteditable div>').trigger($.Event('keydown', {which: 13}))
I've tried this from both the content-script environment and the actual page environment (via both an injected script that responds to postMessage and the Chrome console)
I've also tried triggering the event on the document, from each context.
Nothing seems to happen.
2) Same thing, but with VanillaJS event triggering. relevant StackOverflow question
also from both environments
Nothing happens
3) At this point I realized that this is React and it uses it's own SyntheticEvents, so I basically copy/pasted the Simulate function from ReactTestUtils that's supposed to help testing by simulating events and ran that within the page's environment (grabbing references to the required objects via Facebook's frontend require function).
Also does not work. The function executes fully and without errors, but there's no response from the application.
I've tried this with mostly keydown events, because that has the most listeners attached to it.
I'm aware of these questions, but they haven't helped my understanding: Force React to fire event through injected JavaScript
It's unclear based on your description whether or not this is an issue, but SyntheticEvent has caused me pain before due to the fact that the object is reused. There's a note in the React docs about this:
If you want to access the event properties in an asynchronous way, you should call event.persist() on the event, which will remove the synthetic event from the pool and allow references to the event to be retained by user code.
If you aren't immediately using the event, or if you are trying to pass it into a new scope, you'll need to persist() it.
Related
I am working on a Blazor WASM project where we are using an internal HTML/JS library (a requirement that I can't get around). This library has custom events on it's components that often replace standard events. For example, the <select> control has a valuechanged event that takes the place of a standard change event (the change event is no longer emitted for this custom <select>). It also has completely custom events, such as a sort event on its <table> element.
I need to be able to work with these events, but so far have not been able to. I've tried to follow the guide here: https://learn.microsoft.com/en-us/aspnet/core/blazor/components/event-handling?view=aspnetcore-6.0#custom-event-arguments, and gotten it set up correctly I believe (because intellisense recognizes the #on____ line), but the code to execute on those events never gets called. I'm not sure if that's because I don't have a browserEventName, or for some other reason. I've also tried the instructions here: https://stackoverflow.com/a/67595043, but again, have not had any success.
Is there a way to wire up listeners/actions to the custom events emitted in the library? The closest I've been able to find on SO to my specific issue is an unanswered question from a few years ago: How to retrieve Web Component custom event result with Blazor.
In chrome dev tools, I consistently see a 100ms blip on the performance timeline when my mouse first enters the DOM in my React project. The function call is listed as a mouseover event callback in the react DOM, but I can't find any info in the react docs about why this event occurs. Is it because events are delegated to the window in react, or is it background work that needs to be done to prepare for other events?
It's off-putting to see such an intense function call that I never called for, especially if I am planning my own work to be done at the same time. If anyone has any insights, I would be grateful!
EDIT: It doesn't always happen under mouseover. Sometimes it is just a function call.
a onmouseover is the synthetic javascript event that is being registered here when you mouse is entering the DOM. These events have corresponding synthetic React events, which can be found on this link. Most of the events from JS on a DOM have a corresponding event in React. You can find all of them enlisted on the given link.
This may be part of the answer as well. Taken directly from the source code. I think this 'blip' is setting up the React event emitter. So React is using event delegation and this emitter is responsible for delegating.
I am looking to create events in Javascript using the same methodology as JQuery- Does anyone know how JQuery does it?
My reasoning is that using raw Javascript such this:
var myEvent = new CustomEvent("userLogin", eventProperties);
...does not actually work on Android native browser, as it does not support DOM Level 3 like Chrome and other browsers do.
However, JQuery does work on Android's stock browser, and simply uses:
$.event.trigger('MyEvent');
My question is, what is the code behind this? I tried to find it by going through JQuery's source code, but cannot get my head around it!
The fundamental thing here is this: When you hook an event handler up with jQuery, jQuery doesn't directly add that handler to the DOM element. Instead, jQuery hooks up a handler of its own on the DOM element (if it doesn't already have one on it). When the event occurs, jQuery looks at the list of jQuery-registered handlers for the event and fires them in order. (There are several reasons for this; initially it was primarily around IE memory leaks and the fact that IE fired handlers in one order, and everyone else in a different order; so jQuery took over and ensured the order.)
(You might be able to see where I'm going with this...)
So when you use trigger, jQuery sends the synthetic event to the DOM element, but it doesn't rely on that synthetic event to work; it calls the handlers you've registered through jQuery directly. In fact, it sets a flag so that it knows that it's done that, so if the browser does send the event to jQuery's handler for it, jQuery knows to ignore it (since it's already done its work).
You can see this in all its glory starting with line 4,464 of the current uncompressed jQuery file.
So basically jQuery's build its own pub/sub system, and only uses the browser event system as an input to it. So custom events don't usually have to talk to the browser at all.
Other javascript is changing the value of an input and I was wondering if there was a way to detect the change.
This question has nothing to do with Keyup or Change. This is not being typed in by the user it is being changed by other javascript though various actions of the user.
When changing an event programatically, you can trigger a change event to make sure event handlers that are attached to the element are fired. jQuery has a trigger() method to do this:
$('#elementID').on('change', function() {
alert( this.value );
});
$('#elementID').val('some new value').trigger('change');
The quick run-down of what I am going to say is: there is no way other than to modify the third-party scripts to output stuff, or to use setInterval (costly).
The bottom line of this issue is a simple one, that does not appear to be so at first: How can you get your scrips to communicate with each other?
When a script modifies the value of an input through JS methods (i.e. not user input), they have to go through specific hoops to get the "change" event to fire (they can fire it manually by calling it, which most devs never do and is easily forgotten when writing code). In practice, people tend to rely on the observation events (user-defined ones) to track code changes. This is very similar to DOM events - you bind callbacks to your script, which allow you to tap callbacks in that will fire whenever your scripts do something interesting (like modifying inputs. This is just one example). You then teach your scripts and developers to fire events on useful stuff using the callbacks to notify other scripts.
A great library for this is Postal, which is originally a Node library. jQuery also has an event system you can tap into. However, if you want to roll your own, all you have to read into is the Observer design pattern. It is trivial: you bind a function to your object to pick up callbacks, and another to fire them. Whenever you change the thing, you fire the callback. Simples.
Failure to do so means setInterval. Sucks, but there you go :-(
Before I get into the details of this problem, I'd like to make the situation clear. Our web analytics company works as a consultant for large sites, and (other than adding a single SCRIPT tag) we have no control over the pages themselves.
Our existing script installs handlers using "old" way (a fancy version of element.onclick = blah; that also executes the original handler) which is completely unaware of "new" (addEventListener or attachEvent) handlers on the page. We'd like to fix this to make our script able to run on more sites without requiring as much custom development.
The initial thought here was to have our own script use addEventListener/attachEvent, but this presents a problem: of the client's site sets a handler using the "old" way, it would wipe out the handler we installed the "new" way. Quick and dirty testing shows this happens in both IE7 and FF3, although I didn't test the whole range of browsers. There's also a risk that if we use the "new" way after the page's event handlers are already set, we could erase their handlers.
So my question is: what safe technique can I use to add an event handler in Javascript using addEventListener/attachEvent that works regardless of how other event handlers on the page are installed?
Please remember: we have no way of modifying the site that our script is installed on. (I have to emphasize that because the default answer to questions like this is always, "just rewrite the page to do everything the same way.")
Can you try your quick-and-dirty testing again? This doesn't happen for me in FF3.
elem.onclick = function() { alert("foo"); };
elem.addEventListener("click", function() { alert("bar"); }, false);
Both handlers fire for me when I click on the element.
I'm guessing you forgot the final boolean argument in addEventListener (whether to use the capture phase). I'm also guessing you forgot that IE's attachEvent needs onclick, not click.
addEventListener/attachEvent is safe in a sense you ask. They add a new event handler to a Node without altering any handlers previously added to it (even once assigned through a property onxxx). For a company that bring some to a foreign page using addEventListener/attachEvent must be the only practice. Assigning onxxx handler via properties indeed would break hosting pages scipts (that have been previously assigned the same way)