There is an iFrame with buttons inside that I cannot change directly. The requirement is to use this specific iFrame. Inside this iFrame, there have many buttons with the same classname that the user can click to navigate to another page. Outside the iFrame, I have a form of user data and tracking to know when the user has made any changes.
Note: I'm not actually using an iFrame, but the basic idea is I have content that I cannot directly change.
I have a message when the user has unsaved changes and they click on any item inside the iFrame ~ "You have unsaved changes, are you sure you want to discard them?".
I would like to override the original function's definition to have my blocking confirmation logic in front of whatever logic is already there. When the user confirms, I need to continue the original navigation.
The best way I can think to do this is to query the button element and override the button.click() function with an my popup message and then the original function call. Maybe something like this:
useEffect(()=>{
const elements = document.getElementsByClassname("classname");
for (let element of elements){
const originalFunction = element.onclick // <--
element.onclick = () => {
if (blocked) {
confirmation({
content: "You have unsaved changes, are you sure you want to discard them?",
proceed: "Discard changes",
cancel: "Cancel",
handler: function () {
discardChanges();
originalFunction(); // <--
}
});
} else {
originalFunction(); // <--
}
}
}
return ()=>{
restoreOriginalFunctionDefinitions(); // <--
}
},[]);
- What is the correct way to inside a function in-front of another function definition?
- Is it possible to do this and then restore the original definition when the element unmounts?
- Is there just a better way to do this?
I've tried the following useEffect
useEffect(()=>{
const elements = Array.from(document.getElementsByClassName(watchingClassName));
console.info("elements", elements);
elements.forEach((element)=>{
const htmlElement = element as HTMLElement;
AdviceFunction(htmlElement.click, blocking, "Are you sure", "Discard",onDiscard,"Cancel" );
});
}, [])
Advice Function has the following definition:
const AdviceFunction = (
originalFunction,
blocked,
message,
discardCaption,
discardAction,
cancelCaption
) =>
function (...args) {
console.info("advice", { this: this, originalFunction, blocked });
if (blocked) {
confirmation({
content: message,
proceed: discardCaption,
cancel: cancelCaption,
handler: function () {
discardChanges(discardAction);
originalFunction.apply(this, args);
}
});
} else {
originalFunction.apply(this, args);
}
};
Actual result: useEffect successfully queries the dom for the buttons. When a button is clicked, only the original function is ran and the console.info in AdviceFunction is never logged.