Best practice accessing document object in ReactJS - javascript

Is it bad practice to access the document Object directly when working with a framework like React.
I am using an external barcode scanner and I want to detect when number is scanned and populate a specific field. I want to avoid tracking what field is in focus.
Here is my code
render(){
....
document.onkeypress = (e) => {
e = e || window.event;
const digit = e.key;
if(e.target.nodeName === 'BODY' && digit.match(/[0-9]/i)){
console.log(digit);
}
};

document.onkeypress is likely to be poor practice regardless of whether you're using React. Instead, document.addEventListener("keypress", ...) (and be sure to do it only once.)
Separately, hooking up event handlers in render would certainly not be best practice. If you need to hook up a handler to document for some reason, you'd do that in componentDidMount (and you'd remove it in componentWillUnmount).

Related

is there a way to override event dispatch from browser or user agent?

What I want is, when an element receive an event, I want it to do "something" first, that "something" could be is to evaluate whether to call the registered event listener or not.
I able to override manually dispatching event through calling .dispatchEvent(event) method but not event sent/dispatch by browser e.g. user click on a button.
Here my attempt:
let evtDispatcher = EventTarget.prototype.dispatchEvent;
let foo = false;
EventTarget.prototype.dispatchEvent = function(evt) {
if (foo) {
console.log('Event Sent');
evtDispatcher.call(this, evt);
} else {
console.log('No Event Sent');
}
}
function displayMe(evt) {
document.getElementById('span-id').innerHTML = 'Clicked';
}
let bttn = document.getElementById('bttn-id');
bttn.addEventListener('click', displayMe);
//When user click the "button" tag
// Desire result: don't call the event listener and log "No Event Sent" on console
// Actual result: event listener is called and "Event Sent" is log on console
bttn.dispatchEvent(new Event('click'));
//manual dispatch works
Here's my attempt code on JsFiddle
The answer is "sometimes".
I wouldn't recommend trying to override dispatchEvent() or any of the other native methods, because, it won't work for a lot of things. Much of the event handling stuff happens at a level below where you can access with JavaScript.
Instead, you can try to implement it making use of event capture.
If you provide true to the useCapture parameter or capture option of an event, you'll basically give that element priority over others that aren't using capture. If you do this on html or body at the top-level, they'll get a chance to look at, and potentially stopPropagation() of the event, based on whatever arbitrary logic you want.
You can see that happening with this little sample.
const allow = document.querySelector('input');
const div = document.querySelector('div');
const span = document.querySelector('span');
const button = document.querySelector('button');
div.addEventListener('click', event => {
console.log('div');
if (!allow.checked) {
event.stopPropagation();
}
}, { capture: true });
span.addEventListener('click', () => console.log('span'));
button.addEventListener('click', () => console.log('p'));
<label>Allow through? <input type="checkbox"></label>
<div>
<span>
<button>Click Me</button>
</span>
</div>
So, if you do this for every possible event, you can usually do what you want. There are some exceptions though, hence the "sometimes" above, which aren't super well defined and are done by browsers to try to prevent fraud and hacks and whatnot. I don't know of a single comprehensive list of where you can't override, but if you don't truly need EVERY event to do this, it might not matter.
There also isn't a wildcard event, so you'll have to hook it up to each event, but there are ways to implement a wildcard event yourself.
One final note, since you mentioned user agent. If you are trying to do this for any security purposes: don't. Or, at the very least, ensure you also still have full protections on the back-end. Any "security" on the front-end is just security theater and easily bypassed by someone with enough knowledge, no matter how well implemented.

Understanding Event Handlers in JavaScript [duplicate]

I don't understand the motivation behind window.event or window.event.srcElement. In what context should one use this? What exactly does it represent in the DOM?
Here what w3school says about event object:
Events are actions that can be detected by JavaScript, and the event
object gives information about the event that has occurred.
Sometimes we want to execute a JavaScript when an event occurs, such
as when a user clicks a button.
You can handle events using:
node.onclick = function(e) {
// here you can handle event. e is an object.
// It has some usefull properties like target. e.target refers to node
}
However Internet Explorer doesn't pass event to handler. Instead you can use window.event object which is being updated immediately after the event was fired. So the crossbrowser way to handle events:
node.onclick = function(e) {
e = e || window.event;
// also there is no e.target property in IE.
// instead IE uses window.event.srcElement
var target = e.target || e.srcElement;
// Now target refers to node. And you can, for example, modify node:
target.style.backgroundColor = '#f00';
}
Not sure if this difference has been changed in newer browser versions but basically, "In the Microsoft event accessing model there is a special property window.event that contains the last event that took place." (from reference)
So, to write an event handler compatible across browsers you'd need to do something like this:
function doSomething(e) {
if(!e) {
var e = window.event;
}
var ele = e.target || e.srcElement;
// get the clicked element
// srcElement for IE, target for others
}
element.onclick = doSomething;
Reference:
http://www.quirksmode.org/js/events_access.html
function IndentifyMe(){
alert("You clicked on " + window.event.srcElement.tagName);
}
<body onclick = "IndentifyMe()">
Try this code, with lots of element in body tag, and try clicking different element
Events are the lifeblood of user interaction. Without events, you
couldn't interact with the page.
Event handlers are used to invoke some JavaScript when a certain action happens. If you want some
behavior to be triggered when the user moves their cursor over an element, you use the onmouseover
event handler.
"DOM Scripting: Web Design with JavaScript and the Document Object Model: Second Edition"

Distinguish JavaScript events

What is the best way to distinguish events in JavaScript.
Actually there are two points I am interested in. The first one is are there something like id in event (it would be very useful foe debugging purposes). And another point are there better ways to distinguish mousedown and mousedown&touchstart events.
Let me tell you my story. I met the problem that if you add two dom events to a node with triggers mousedown and touchstart, then on mobile devices both mousedown and touchstart run.
The first solution I found was to run
event.preventDefault();
event.stopPropagation();
at the beginning of each listener function.
But then I found out an event delegation pattern and started to work with analytics, all that disallowed to use the previous approach, so I come up with the following solution:
let lastEvent = null;
const specificListener = function(e) {
if (lastEvent === e) {
return; //already run the code due to another listener
}
/*
logic goes here
*/
lastEvent = e;
};
And now I am interested whether or not it is possible to compare events in a different way (different from event1 === event2, hope to find out about something like event1.id === event2.id)?
Thank you.
Instead of trying to differentiate the events, just subscribe to mousedown only, as it is fired anyway. That's the most simple solution I'd say.
Or, you could try to detect which event system is supported and only subscribe to the appropriate one:
var eventType = document.ontouchstart != null ? 'touchstart' : 'mousedown';
document.addEventListener(eventType, (e) => { ... });
A third solution (possibly) would be to use PointerEvents only, but that depends on the platforms you need to support.
https://caniuse.com/#search=pointer%20events
If you for sure cannot use one of these approaches: Every event should have a timestamp property (not sure if it is named that way), maybe you can find a way to distinguish two events with it.

JQuery - What is the use of event.originalEvent.preventDefault()?

In a book, the code for handling mouseDown event is like this:
mousedownhandler: function (ev) {
mouse.down = true;
mouse.downX = mouse.x;
mouse.downY = mouse.y;
ev.originalEvent.preventDefault();
}
So my question is why use ev.originalEvent.preventDefault(); but not ev.preventDefault(); or return false; in this case (HTML5 game)?
jQuery alters the event methods / data in the returned event.
Using event.originalEvent, you're able to retrieve this back.
For example jQuery strips the dataTransfer api for dragged items, using the originalEvent you can use it again.
docs: "jQuery normalizes the following properties for cross-browser consistency ... To access event properties not listed above, use the event.originalEvent object"
In the proposed case it's used to access the preventDefault method (which stops the default action) as it's not included in the jQuery event.
See the definition of preventDefault in jQuery 3.1.1:
jQuery.Event.prototype = {
// ...
preventDefault: function() {
var e = this.originalEvent;
this.isDefaultPrevented = returnTrue;
if ( e && !this.isSimulated ) {
e.preventDefault();
}
},
// ...
};
So basically it will just call native preventDefault. If you are using jQuery I would use its method, it will also update isDefaultPrevented which might be useful if you want to check it (but you could also use native .originalEvent.defaultPrevented).
If you don't care about isDefaultPrevented and know the event has not been simulated by jQuery, then calling native preventDefault might be few milliseconds faster. That's the only potential advantage I can think of, but this definitely won't be a bottleneck.
Returning false in a jQuery event listener is like using both preventDefault and stopPropagation.
I use to know if the event was actually triggered by a physical mouse click. This is useful for avoiding the use of captchas on submit forms.

Storing arbitrary data in an $.event

Here is my code:
var e = jQuery.Event( "keydown", { keyCode: 64 } );
There is data being attached to the event in the second parameter. Now I have seem that kind of syntax in a lot of plugins and was wondering, what's the use of attaching arbitrary data to a $.event/custom event?
I have seen the jQuery docs event object and also trigger.
I am wondering, if the only usage of attaching data to a event is as follows:
var e = jQuery.Event( "keydown", { keyCode: 64 } );
// above is the line I am having difficulty understanding
// the usage of arbitrary data with the $.event is quite
// elusive to a novice developer like me
$(window).on('keydown' , function(e){
console.log('key 64 pressed');
});
press = function(){
$(window).trigger(e);
}
setTimeout(function(){
press();
}, 2000);
JS Fiddle here
I.e. triggering an event on a specific key or a specific element, I mean is this the only use of attaching arbitrary data to an $.event?
Sometimes you are using your code that behaves in some way depending on the interaction.
In your example, you are "manually" triggering the keydown event on that input in order to "trigger" the event-listeners listening to this event.
Probably on this example you have a idle logout system going on and you activated something to keep the session alive on your UI as long as needed.
The other day I had to use something similar in order to keep a dropdown open in a third party plugin that was closing a drop down on selection after a search.

Categories

Resources