How to Stringify Event Object

How to stringify event object?

You won't be able to serialize an event object with JSON.stringify, because an event object contains references to DOM nodes, and the DOM has circular references all over the place (e.g. child/parent relationships). JSON can't handle these by default, so you're a bit out of luck there.

I'd suggest to look at How to serialize DOM node to JSON even if there are circular references? which has a few suggestions on how to serialize a DOM node. Also, the following questions seem to have useful information:

  • How to save an object with circular references?
  • Stringify (convert to JSON) a JavaScript object with circular reference

JSON libraries able to handle circular references seem to be

  • JSON-js (see cycle.js)
  • dojox.json.ref

Alternatively, you could delete all references to DOM nodes if you don't need them, and then serialize the object. You shouldn't do this after all. See @PointedEars comment :)

Stringifying event object works, but is practically empty

JSON.stringify ignores non-enumerable properties, and most of the properties of a MouseEvent are (apparently) non-enumerable:

document.querySelector('button').addEventListener('click', ev => {  let props = ['isTrusted', 'target', 'clientX', 'clientY', 'layerX', 'layerY'];  props.forEach(prop => {    console.log(prop + '?', ev.propertyIsEnumerable(prop));  });});
<button>Try it!</button>

JSON.stringify losing properties - Logging and saving all javascript events

There could be a couple reasons for this. Most likely is those properties are not enumerable which causes them to not be included in JSON. (Properties are defined as enumerable via Object.defineProperties.) See:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#Description

I would recommend explicitly declaring which properties you want to POST, since you probably don't need all of them anyway:

axios.post('/api/logger', JSON.stringify(events.map(event=>{
return {
altKey: event.altKey,
bubbles: event.bubbles,
// etc...
}
}));

event listener attached to canvas only receives {isTrusted:true} object in codeSandbox

That sandbox has a lot of code, I'm just going to focus on what you have here...

The mouse event object is complex and most likely JSON.stringify is taking a shortcut; and correct if you try to output the entire object it will be slow or it could crash like you describe, but there are other properties there, you can see it on the sample below.

var canvas = document.querySelector("canvas")
var ctx = canvas.getContext("2d")
ctx.fillStyle = "red"

for (let i = 10; i < 100; i += 10 )
ctx.rect(i, i, 50, 50);
ctx.stroke();

canvas.onmousedown = function (event) {
console.log(JSON.stringify(event));
console.log(event.x, event.y);

ctx.beginPath()
ctx.arc(event.x, event.y, 5, 0, 8)
ctx.fill();
};
body { margin: 0 }
<canvas id="canvas"></canvas>

How to access js event object in a super type that is called from a subtype?

This

UiResultsItemInfoParser.prototype = new EvntParser();

is an opt-repeated anti-pattern, and the root of your issue. EvntParser expects an argument and assumes it was given it (this._evntInfo.time = e.timeStamp.toString()), so it fails when you do the above.

Instead:

UiResultsItemInfoParser.prototype = Object.create(EvntParser.prototype);

That creates an object that has EvntParser.prototype as its prototype, but without calling EvntParser. (Then your next line, which is exactly right, fixes constructor on the resulting object.)

Later, you're doing the right thing by doing EvntParser.call(this, e); in your subclass constructor. So it's really just the one line.


Since you're using arrow functions, you must be working in an ES2015 environment. That means you can use the new class syntax, which does all this fiddly hooking things up for you:

class EvntParser {
constructor(e) {
this._evntInfo = {};
this._evntInfo.time = e.timeStamp.toString();
this._evntInfo.type = 'event';
}
set evntInfo(e) {
this._evntInfo.time = e.timeStamp.toString();
this._evntInfo.type = 'event';
}
get evntInfo() {
return JSON.stringify(this._evntInfo);
}
}

class UiResultsItemInfoParser extends EvntParser {
}

Note how you don't even need to define a constructor in UiResultsItemInfoParser; when you don't, the JavaScript engine defines one for you that calls super with all the arguments it receives.


Side note: This:

this._evntInfo = {};
this._evntInfo.time = e.timeStamp.toString();
this._evntInfo.type = 'event';

can also be written

this._evntInfo = {
time: e.timeStamp.toString(),
type: 'event'
};

if you like (even before ES2015). Exactly the same object is created.



Related Topics



Leave a reply



Submit