JavaScript variable scoping - persisting state? - javascript

I have the following setup, and I need to know how to persist state.
1.) An external web page uses ajax to load and display a .jsp file, which contains javascript.
2.) Once this rendering is complete, javascript in the .jsp file must be called to perform an action based on the results that occurred during rendering. Specifically, the document does action on $(document).ready, and those actions dictate what must be done on later function calls.
The question I have is this: How do I persist the data and state created when the page is loaded? I tried something like this:
External:
ajax to test.jsp
Internal test.jsp
var saveMe = {};
function getsCalled()
{
saveMe = {'a':function(){return false;}};
}
function needsData()
{
//???
}
Later...
External:
needsData();
Nothing I seem to attempt is working. What would be the best way to persist state in this situation?

If you want to know about scoping read this. It might help you to work out what is going on.

Have you tried declaring saveMe outside of the $(document).ready? Then you should be able to change the value from inside the $(document).ready as well as from the external script. I'm not sure how the scoping works for javascript variables from an ajax call though, so I'm not sure if this would actually work.

Making the variable a member of the function object worked swimmingly.

Related

Share global variables between aspx and Vue pages

Before anybody starts screaming at me for using global variables, I have a few things to say:
This is only for one variable and will only be used temporary (my estimates says that it will be gone within one year)
I'm open for suggestions on how to solve this a better way
Our project has a bit of a unusual setup. We have an old ASP.Net website, that we are slowly converting to VueJs, page by page. Due to this, we are using UMD
Currently Vue is used for the menu, showing content, etc. When showing an old aspx page, we are using iframe. My goal is for my Vue to be able to catch events thrown from the open aspx page
For this I thought the mitt emitter would be perfect for the job. I'm using it in my Vue project already
On the code side of things, I have the following:
I have a Toolbox.js file, where I try to keep my global variable
var emitter;
async function ClickFromOldPage()
{
emitter.emit('test');
}
In mounted in my vue file (the first thing that opens) I'm setting the global variable
mounted()
{
window.emitter = window.mitt();
window.emitter.on('test', this.Test);
},
And then I have an aspx page that calls ClickFromOldPage
Both the vue file and aspx file is loading Toolbox.js like this
<script src="../Vue3/Javascript/Toolbox.js"></script>
From what I could gather around the net, this should do it, but emitter is undefined when calling Toolbox from the aspx page
Another way was by using top to set/get variables, but this gives the same result
I also tried localStorage, but this can't handle complex objects like the emitter
The only other way to handle this challenge I can think of, is by using cookies or localStorage, where the aspx page writes 'Clicked' (or whatever), then have a function in Vue that checks for said data every second or so. This doesn't sound like a good solution, but the only solution I can come up with
Any other ideas?

JSP variable initialization is happening after JS runs

I'm initializing a JSP string inside a Liferay portlet:
String json = "{}";
// returns json
json = LiferayPortlet.makeCurlCall();
...
<script>
$(window).load(function(){
//initialize js variable
jsData = "${json}";
// initialize the page
initializePage(jsData);
});
</script>
The issue I'm having is that LiferayPortlet.makeCurlCall(); is returning json, but jsData is not being initialized to it, instead its being set to "". Is there a way to initialize jsData to the json that is being returned from the function above?
Don't do it
You cannot initialize a JavaScript variable with a scriptlet or JSTL. The Java code is executed on the server and will not execute in top down order on your jsp page.
While I don't recommend this you can use the following
<script type="text/javascript">
var message = '<c:out value="${json}"/>';
</script>
That will technically work - however I want to stress that I do not recommend this. Maybe you can explain exactly what you are trying to accomplish and we can recommend a more optimal way of doing it.
JSTL v. Scriplets
You might also have a scope issue using JSTL and scriplets together indiscriminately. They are of different scopes. JSTL works with the following scopes.
page
request
session
application
Scriplets are in the page scope always. So while your code doesn't contain this issue it most likely will be something you will encounter.
Recommendation
If you are using Liferay, I suggest you learn Alloy UI (a JavaScript library) and become comfortable with their AJAX modules. Generally, when I see the code you posted, it is better to have an AJAX function that makes a GET call to your portlet for the JSON when it is needed.

Setting a variable of a javascript from an other, in javascript

I have the following problem:
In file (let a.js be) I have:
var kindofdisplay ;
In an other file ( let b.js be)
I get the information to set kindofdisplay.
Now, I would like to set kindofdisplay from file b.js so that when a.js is executed it will be able to process the variable in a correct way.
Many thanks
As Raja pointed out. If you can access the kindofdisplay variable on b.js, you can change it. You just need to take care not to declare it again.
You can try give a default value like:
var kindofdisplay='none';
And check if that's the value the variable has when on b.js. If it's not, you are probably declaring it again.
If you're using the two javascript files on different web pages, you could always set the variable as a cookie (providing you don't need it to be secure).
Have a look at this tutorial about cookies.
Another way to do this would be to put the script that defines the function for setting the variable in one file, link it to both pages that you need the variable to exist in and call the function on each page.
Of course, as a couple of people have already explained, if you're using the two javascript files on the same page, there's no need to do this - just ensure that the variable has the appropriate scope.

Yabble - accessing functions loaded by yabble

Am having a problem with Yabble that I have not been able to solve.
From within my main html I load all of my js using yabble
<script>
require.setModuleRoot('./javascript/');
require.run('main')
</script>
I have a bunch of js (gamejs related). In one file I have function changeSimulationSettings(). Later within the same page I want to take user input and access the gamejs objects and change their state. The problem I am having is that I am unable to call changeSimulationSettings. It is not defined within the current context. Yabble does so much magic I am unable to find where it is defined or how to access.
<div>
<button type="button" onclick="updateSettings()">Update-Settings</button>
</div>
<script type="text/javascript">
function updateSettings(){
// access function defined in a js loaded by yabble
i.e. changeSimulationSettings()
}
</script>
All of the js is definitely being loaded as I have got functions calling each other from different files which does work. However, I am unable to call anything from js embedded within the entry web page.
Any help would be appreciated as I have been stuck on this one for hours and hours.
Thanks,
Code defined in modules is isolated and not available globally.
I would do it the other way around: from within a module attach an event handler. Do not use "onclick=" but instead in a module, where you have changeSimuSettings available, do something like this (e.g. using jquery or plain DOM):
$('button').click(changeSimulationSettings)
This is cleaner and you are not leaking globals. If you insist on doing it your way, you could export changeSimulationSettings to global and use the code you already have. Like so (I would not recommend that):
window.changeSimulationSettings = function() {...

I have an issue with inline vs included Javascript

I am relatively new to JavaScript and am trying to understand how to use it correctly.
If I wrap JavaScript code in an anonymous function to avoid making variables public the functions within the JavaScript are not available from within the html that includes the JavaScript.
On initially loading the page the JavaScript loads and is executed but on subsequent reloads of the page the JavaScript code does not go through the execution process again. Specifically there is an ajax call using httprequest to get that from a PHP file and passes the returned data to a callback function that in onsuccess processes the data, if I could call the function that does the httprequest from within the html in a
<script type="text/javascript" ></script>
block on each page load I'd be all set - as it is I have to inject the entire JavaScript code into that block to get it to work on page load, hoping someone can educate me.
If you aren't using a javascript framework, I strongly suggest it. I use MooTools, but there are many others that are very solid (Prototype, YUI, jQuery, etc). These include methods for attaching functionality to the DomReady event. The problem with:
window.onload = function(){...};
is that you can only ever have one function attached to that event (subsequent assignments will overwrite this one).
Frameworks provide more appropriate methods for doing this. For example, in MooTools:
window.addEvent('domready', function(){...});
Finally, there are other ways to avoid polluting the global namespace. Just namespacing your own code (mySite.foo = function...) will help you avoid any potential conflicts.
One more thing. I'm not 100% sure from your comment that the problem you have is specific to the page load event. Are you saying that the code needs to be executed when the ajax returns as well? Please edit your question if this is the case.
I'd suggest just doing window.onload:
<script type="text/javascript">
(function() {
var private = "private var";
window.onload = function() {
console.log(private);
}
})();
</script>
On initially loading the page the js loads and is executed but on subsequent reloads of the page the js code does not go through the execution process again
I'm not sure I understand your problem exactly, since the JS should execute every time, no matter if it's an include, or inline script. But I'm wondering if your problem somehow relates to browser caching. There may be two separate points of caching issues:
Your javascript include is being cached, and you are attempting to serve dynamically generated or recently edited javascript from this include.
Your ajax request is being cached.
You should be able to avoid caching by setting response headers on the server.
Also, this page describes another way to get around caching issues from ajax requests.
It might be best not to wrap everything in an anonymous function and just hope that it is executed. You could name the function, and put its name in the body tag's onload handler. This should ensure that it's run each time the page is loaded.
Depends what you want to do, but to avoid polluting the global namespace, you could attach your code to the element you care about.
e.g.
<div id="special">Hello World!</div>
<script>
(function(){
var foo = document.getElementById('special');
foo.mySpecialMethod = function(otherID, newData){
var bar = document.getElementById(otherID);
bar.innerHTML = newData;
};
//do some ajax... set callback to call "special" method above...
doAJAX(url, 'get', foo.mySpecialMethod);
})();
</script>
I'm not sure if this would solve your issue or not, but its one way to handle it.

Categories

Resources