When I have a variable defined into server context, sometimes I need use it into javascript context; for example the session id.
What's the better way to do it?
I want to separate javascript files and view files (in my case jsp); for the moment I have found 2 ways:
1) myVariables.js.jsp: create a jsp file that returns javascript code
myLib = {
sessionID: "${sessionId}",
[...]
}
and import it as javascript into the jsp view file:
<html>
<head>
<script src="myVariables.js.jsp"></script>
[...]
</head>
<body>
[...]
</body>
</html>
I'm able to get the session id writing: myLib.sessionId.
Pros: handy and rapid.
Cons: write a jsp file that acts as js.
2) Save the server variable into hidden input fields (for example, in the main part of the template):
<html>
<head>
<script src="myLib.js"></script>
[...]
</head>
<body>
<form id="myVariables">
<input type="hidden" name="sessionId" value="${sessionId}" />
[...]
</form>
[...]
</body>
</html>
I'm able to get the session id writing a specific function into myLib.js library:
myLib = {
sessionId: function() {
return $("form#myVariables > input[name=sessionId]").val();
},
[...]
}
Pros: javascript and view completely separated.
Cons: more code to write; little harder to understand than the previous.
In my opinion first way is better because your pages will be clean and more readable. That'is very important! ;)
Best regards
There's a third way that I think takes the best of both of your suggestions: An inline script tag containing the variables:
<html>
<head>
<script>
var myLib = {
sessionID: "${sessionId}",
[...]
};
</script>
</head>
<body>
[...]
</body>
</html>
No separate JSP to write. Just as separated as the second solution in your question, as the JavaScript is tied just to the myLib, exactly as the JavaScript in your second solution is tied to the structure of the form.
There's a benefit to your first solution we should call out: It allows the HTML to be cached by the browser (by separating the variables into a separate request, e.g., for the .js.jsp). Combining the variables with the HTML (either as above, or the second approach in your question) means the HTML has to be served with caching diminished or disabled.
Related
I want get the custom attribute in AEM HTL use the request object. this attribute already set to request through javascript use API. like this:
test.js
use(function () {
request.setAttribute('someKey', 'someValue');
});
test.html
<html data-sly-use.logic="test.js">
<!-- some code ... -->
<body>
<div>${request.attribute['someKey']}</div>
</body>
</html>
result:
<html data-sly-use.logic="test.js">
<!-- some code ... -->
<body>
<div></div> <!-- empty -->
</body>
</html>
We can get request attribute without Java? Many thanks.
Since HTL syntax is rather declarative than imperative, calling methods/functions with parameters is not supported. That means you cannot do something like ${request.getAttribute('someKey')}. Unfortunately, the Java HttpServletRequest API does not expose the attributes as a map (it does that for parameters) so you cannot do ${request.attributeMap['someKey']} either, you'll need to fetch the attribute and expose it from your use-object/model.
Though you cannot send request attribute the way you are trying to do right now , you can set that as a variable from your server side JS and access it in your code.
In your test.js
use(function () {
return {
someKey: someValue
};
});
In your test.html
<html data-sly-use.logic="test.js">
<!-- some code ... -->
<body>
<div>${logic.someKey}</div>
</body>
</html>
This should print the someValue as output for you.
I have tried out a scenario which I'm confused of. This is may be javascript 101, but I'm missing a point here.
Assume you have JS library which has a global variable defined. Also it has two functions called setData and retunData .I have separate html with a script within it's Head tag. This HTML file imports above library.
Now on the html I have a text field with two buttons.Buttons are send data and view data. The flow is, user type something and click send Data button. On its onClick I'm getting the text value and pass it to above JS library setData function which sets data to global variable. When i click the view data , on it's onClick it will call the returnData functio of JS Library and I'm alerting the value.
My question is, if I run my html on two browsers , and from one browser if i set the value "ONE" , on the same browser when i retrieves it says "ONE". On the second browser if returned the value it should be "ONE" because that variable is global and value is already set by first browser.
But it works as two requests. it won't override the global variable value. I know it should be the ideal case. But WHY? That's a global variable right? I hope my question is clear.
on the jsLibrary i have this.
var checkVal;
function setData(val){
checkVal = val;
}
function viewData(){
return checkVal;
}
My html is this.
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<script src="js/jsLibrary.js"></script>
<script src="js/jquery-2.1.1.min.js"></script>
<title></title>
<script type="application/javascript">
function sendData(){
var val = $("#idTextVal").val();
setData(val);
}
function viewData(){
alert(returnData());
}
</script>
</head>
<body>
<input type="text" id="idTextVal">
<input type="button" id="idConnect" onclick="sendData()" value="SEND">
<input type="button" id="idChecj" onclick="viewData()" value="VIEW">
</body>
</html>
WHY? That's a global variable right?
It is global, but for this particular tab/page instance. If you open that same page in other tab, javascript engine will initialize all variables, because it doesn't know that you have other tab.
In your case you have multiple options. Perhaps, the most straightforward is to use serverside storage to preserve state. Or you can use simple cookies/localStorage approach, they are also shared by all pages on the same origin. I would go with WebStorage as simpler:
function setData(val) {
localStorage.checkVal = val;
}
function viewData() {
return localStorage.checkVal;
}
So, lets say you have a page that wants to load from a javascript file and it includes
temp.html file
<script src="example.js"></script>
<p class="one"></p>
Now in the example.js file you have a function that is
function getInfo() {
var place = "foo"
$(".one").html(place);
}
//Edit currently I call the function inside the JS file
getInfo();
My question is how would you connect the two files so that the external javascript file knows that it is pointed to the paragraph with the class one?
Normally when this is in a single page, you would call the function and the info will be set.
I have seen a getScript method and a load method for Jquery. Would that be applicable here?
Any ideas on how to approach this? If you provide some code that will be super helpful.
Thanks in advance.
Looks like you want to execute getInfo() as soon as it's defined (i.e.: example.js is loaded).
You can try this approach:
<script src="example.js" onload="getInfo();"></script>
In your example.js, change getInfo() to something like this:
function getInfo() {
$(document).ready(function() {
var place = "foo"
$(".one").html(place);
});
}
Your language is confusing, but you could use jQuery's $(document).ready function which would suffice. Generally speaking, an externally loaded file should execute where the tag is in the script.
A hack could be to place a tag before the end of your document body, give it an id, and then use $('#id').ready() there. In general though, you could just try coding the transclusion concept (I'm guessing you're used to this) from scratch using intervals and timeouts.
<div id="rdy">
</div>
</body>
Then in your file:
$('#rdy').ready(getInfo);
Just my added opinion, you should consider that Google is up to some not-so-nice things these days, they are long-gone from the "do no evil" mantra.
If we assume you have a JavaScript file that contains this content:
function getInfo() {
var place = "foo"
$(".one").html(place);
}
then your markup will look something like this:
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="example.js"></script>
<script>
$(function(){
getInfo();
});
</script>
</head>
<body>
<p class="one"></p>
</body>
</html>
$(function(){ ... }); is just the simplified version of $(document).ready(function(){ ... });. They both more or less handle the onload event, which fires when page has finished loading.
Is it possible (and a good idea) to pass dynamic data to a JavaScript include file via a hash url?
Such as:
<head> <script src="scripts.js#x=123&y=456"></script> </head>
I am looking for an alternative to inline js in dynamically built pages:
<head>
<script src="scripts.js#x=123&y=456"></script>
<script>
$( document ).ready(function() {
pageInit(123, 456)
});
</script>
</head>
Is it a good idea to avoid inline js? How can you pass dynamic data without ajax which creates a needless roundtrip network request?
Note: The hash bang url is a special because the browsers ignore the hash portion of the url when checking the cache. At least for html files.
So all of these will reuse the index.html file it is in the cache:
index.html
index.html#x=123
index.html#x=345345
index.html#x=2342&y=35435
This same principle should hold true for javascript files. What I hope to achieve is to reuse the cache version of script.js from page to page.
Going to index.php, include this:
<head> <script src="scripts.js#x=123&y=456"></script> </head>
Then going to fun.php include this
<head> <script src="scripts.js#x=898756465&y=5678665468456"></script> </head>
Then going to see.php include this
<head> <script src="scripts.js#session=887987979&csrf_token=87965468796"></script> </head>
From page view to page view, pass whatever info the page needs via the hash bang while at the same time reuse scirpt.js from cache.
So, is it possible to read the hash bang info from within the scirpts.js?
If the HTML file you are creating is dynamic, then just create inline JavaScript. Writing an include will just create an extra request from the browser, which you can avoid in the first place.
Edit:
just include a JavaScript file that reads the URL, you don't need to pass any variables (but of course, you also could):
$(document).ready(function() {
// pseudo code
hashbang = location.href.substr(location.href.indexOf('#') + 1);
if (hashbang.x && hashbang.y) {
pageInit(hashbang.x, hashbang.y);
} else if (hashbang.csrf_token) {
// do something else
}
});
I have controller:
package plugin
class TestController {
def simply = {[name:new Date()]}
}
as you see i pass param name
my view page:
<html>
<head>
<!-- <script type="text/javascript" src="${resource(dir:'resource/js',file:'simply.js')}?color=FA8DFF">-->
<g:javascript>
alert("${name}")
</g:javascript>
</head>
<body>
</body>
</html>
this page run correct - afrer load i see alert window with current date :)
but, when
view page:
<html>
<head>
<script type="text/javascript" src="${resource(dir:'resource/js',file:'simply.js')}?color=FA8DF">
</script>
</head>
<body>
</body>
</html>
and external simply.js file:
alert("${name}")
i see empty alert window. So, my question: how i can pass params to external.js file?
There are two stages in parsing the view when it is displayed to the user. State one is the server executing any code contained in the view page. In your case
${name}
Is turned into the current date since that’s the value from the controller. This means that the text sent to the users browser contains 3/2/2010 instead of ${name}
The second stage that takes place when the user accesses a view is the browser parsing the HTML. The HTML that is sent to the browser depends on what took place on the server. Since in your example the JavaScript is contained in the view ${name} is replaced with the current date on the server. Then JavaScript containing 3/3/2010 is sent to the browser since ${name} was replaced by 3/3/2010 on the server. This means the popup box will contain 3/3/2010. If you include external JavaScript files they never get run through the first step since the browser directly downloads them and does not make a request to the server. This means that the first step never takes place so $[name} does not get replaced with the value from your controller. This behavior is the same weather you use the
<script>
or
<g:javascript>
tag.
In order to pass values from a view into JavaScript located in an external file you should define your JavaScript as functions in external files if you wish to pass parameters. For example in external.js
Function dispDate(theParam)
{
Alert(theParam);
}
Then from your view
<g:javascript src="external.js" />
<script type="text/JavaScript">
dispDate(“${name}”);
</script>
Where external.js is stored in the web-app/js directory.