Custom Code in Page Events

I’m trying to define a function in custom code in my page’s On Page Enter (or On Before Page Enter) handler. I need to call the function in a future event, such as a button press.

image

When I call test(); in custom code in my button’s On Click event, I get an error saying that test function is not defined.

image

How can I define functions in custom JS code that are accessible in subsequent event handlers? I need to do this for integration purposes with another page that is loaded in an iframe, so I need to work with custom code.

Hello @Marc_Chriqui,

you need to invoke your function in this code (after function declaration), and just put this custom function in your On Click handler logic. This way it will be invoked when you click on a button.

Regards,
Stanislaw

Thanks @stanislaw.grin. Yes that would work, however that’s not what I’m aiming for. For reasons too long to explain, I’m looking to define the function in one handler and call it from another. Is that not possible? Doesn’t JS code all get rendered on the page in a way that can be accessed?

How about Custom Functions?
You can use JS code block in them and the functions are reusable.

You can return your function like this:

And then pass it wherever you need it as an argument to another custom function and invoke it:

Regards,
Stanislaw

Thanks @stanislaw.grin, I’ll try and see if that will work for my implementation.

@mark-piller : I definitely use a lot of Custom Functions but in this case I’m trying to make 2 windows communicate via window.postMessage(). I’m experiencing an issue where I’m seeing repeated calls to addEventListener(), so I’m looking to isolate and call it in a Page Enter event handler.

I’m having a really hard time debugging this and would really love some help.

My use case is that I have a page that contains an iframe that hosts a 3rd party page that displays a elearning course activity to the user. The page in the iframe sends me a message, via parent.postMessage(“completeCurrentCourseActivity”), when user completes the course activity. I then call a Custom Backendless Function to mark the course activity as completed for the user.

I added the following custom code to On Page Query because the course activity objectId is passed in the page query.

This is the complete custom code that calls addEventListener() to get messages from the iframe:

I am logging each message that the listener receives from the iframe and what I am seeing, which is very frustrating, is that the message is received MULTIPLE times, cumulatively with each call. What I mean is that on the first postMessage() call, I get the message once. On the second call, processMessage() runs twice (instead of once). Third call, processMessage() runs 3 times. Etc.

It’s like the window seems to be recording previous calls and calls them all again with each new call.

Could the issue be that I’ve added this code in On Page Query? Does that handler just keep adding custom code to the page repeatedly? The fact that I added removeEventListener doesn’t seem to be helping at all. I see multiple calls running even with this call there to attempt to ensure that only one listener/handler is invoked.

Thanks in advance for sharing ideas on how to address this. What I’m trying to achieve is pretty simple. I’m not sure if the fix would be at the JS level or if my running this in On Page Query is the core problem.

To understand the reason we should understand how JS works here.

When we call our custom code we also run Custom Function Coures_complete... which has the following logic:

  • define processMessage
  • remove an event listener with defined function as argument
  • add an event listener with defined function as argument

And the trick is how function definition and passing work. In simple words - each time when this code runs we create a new instance of this function in this scope. And scope every time is new. A new instance of function has its unique link, for better understanding, we name it id. If we rephrase your real code into pseudo code that must look like

define function processMesage // at first run id will be here for example 001

removeEventListener('message', 001) // as the second arg we pass an id of the current listener instance
addEventListener('message', 001)

That means at this moment after every message event we call the function with id 001. But the issue comes from the next iterations.

So let’s look at what happens next. We run the same code and here is the result.

define function processMesage // here will be a new instance, and new id  - 002

removeEventListener('message', 002) // here we pass a new id - 002, because we already loose the previous scope. We can't remove a non existed listener for function with id - 002
addEventListener('message', 002) // but we add a new listener

So, at this moment we have 2 listeners with 2 function(001 and 002) that does the same thing.

As for solutions, there are different approaches.

  1. Create your listener isolated out of page data and only once. Not sure if it’s your case, but it’s a common and easiest way to work with listeners.

  2. At line 23 where you remove your previous listener, we could use the following logic

...
window.removeEventListener('message', window.___MY_EVENT_LISTENER)
window.addEventListener('message', processMessage)

window.___MY_EVENT_LISTENER  = processMessage

That is the trick of how we could save a link(id) to the previous listener function and pass it to the next call of On Page Query handler.

Keep in mind, window it’s a browser namespace, so the strange variable name ___MY_EVENT_LISTENER is chosen not randomly. Browser wouldn’t use it for other purposes.

Let me know if something still unclear.
Regards, Dima.

1 Like

Thank you so much. Reviewing this and will comment back soon.

@Dima I implemented solution #2 and it works super well. I can’t thank you enough! It’s amazing to know JS in such detail the way you do.