It's been four years since OP asked this, but they can accomplish their stated goal as follows:
Create a getter that has a side-effect. (The side effect can be to directly animate your thing.)
class YourThing {
get __doAnythingYouWant() {
// ...like console.log('my thing:', this);
}
}
Alternatively:
var yourObject = {
get __doAnythingYouWant() {
// ...like an animation in DOM... this.myDomElement.style...
}
};
How to use it:
console.log(yourObject);
> {
get __doAnythingYouWant: (...) <-- click here!
}
> "you clicked the dots!"
The downside is you can only invoke the getter once. You could maybe get around this by deleting it and redefining it from within itself, with every invocation. You could make that less hackish by creating some kind of getter-defining function with Object.defineProperties, and some wrapper that takes a regular function and returns a function that does what it normally does, then redefines the getter. Clicking on it once was good enough for me, but if you wanted to you'd do it like this:
function addDebuggerButton(obj, f) {
var buttonName = `__${f.name}`;
Object.defineProperty(obj, buttonName, {
get: function() {
f.apply(this, arguments);
delete this[buttonName];
addDebuggerButton(obj, f);
},
configurable: true
});
return obj;
}
It's important to set the configurable
property, which just lets you redefine it after defining it.
It works:
let numTimesPressed = 0;
addDebuggerButton({a:1,b:2}, function myButton() {
this.c = Math.random();
console.log(`you pressed the button ${++numTimesPressed} times!`, this);
});
> {a: 1, b: 2}
a: 1
b: 2
__myButton: (...) <-- click here!
get __myButton: ƒ ()
__proto__: Object
> you pressed the button! {a: 1, b: 2, c: 0.27574428165568676}
a: 1
b: 2
c: 0.27574428165568676
__myButton: (...) <-- click here again
get __myButton: ƒ ()
__proto__: Object
> you pressed the button! {a: 1, b: 2, c: 0.43171172657344337}
You can modify this as appropriate to work with classes.
If you wanted clicking on different links to have their own different timelines of state (rather than shared state like numTimesPressed
above, which is a global, or somewhat more global, in scope; i.e. such state is shared between different objects), then you could make the function return a callback containing the rest of your computation. You'd have to modify addDebuggerButton accordingly (let callback = f.apply(this, arguments);
, addDebuggerButton(obj, callback)
).
The other horribly hackish way to do this is to write a url like http://127.0.0.1:9999/myLocalWebserver/horribleWorkaround?{"metadata":"etc"}
. The URL would be interpreted by your local webserver you're testing your app out of, and would initiate some kind of push mechanism (or queue onto a poll mechanism), that would propagate to the webpage live. This would flash open a new tab, in which you could display a dummy webpage which auto-closes itself. You could also maybe make this entirely client-side with a webworker that intercepts requests.
... Of course, it would probably be more elegant to compile Chromium yourself with a custom patch...
The third way, since chrome-extension:// urls are allowed, is perhaps to write an extension that converts certain clicks into javascript. There may perhaps be security implications (to be safe, you would not let this run except on whitelisted pages, but even then there are security implications I have not thought of since I'm not entirely familiar with that area).