I'm getting a javascript object via ajax. I need to attach this object to a div in order to be recovered later, for example, on a click event.
If instead of an object I had a variable I would push it into the html tags like this:
'<div variable="'+value+'"></div>';
And I would recover its value like this:
var value= $(this).attr('variable')
Could you suggest me a good approach to do that with objects?
Thank you very much!
The easiest way is to do this:
<div id="myDiv">...</div>
In javascript
var myDiv = document.getElmentById('myDiv');
myDiv._variable = variable;
You can recover this later if you want, simply using the same myDiv variable, or, again, with document.getElementById() or any other DOM method that returns the element.
var variable = myDiv._variable;
The downside of doing it this way is that you can't specify, in the server, or from the markup, which object you want to attach to the element.
If use JQuery you could use the data storrage functionallity
See data documentation of JQuery
//To store value or obj:
$("#myDivId").data("myKey", valueVar);
//Later to load:
var fetchValue = $("#myDivId").data("myKey");
Using a template engine would be the best approach, dividing logic from view, and that way you can parse full object properties to an html.
in this example i use jQuery & UnderscoreJs template engine.
javascript part:
$(document).ready(function(){
var user = { name:"Ofer", age:"29" }
var markup = _.template($("#userTemplate").html(), user);
$('#userContainer').html(markup);
});
html part(goes inside body)
<div id="userContainer">
</div>
<script id="userTemplate" type="text/template">
<fieldset>
<legend>User</legend>
Name: <%= name %><br>
Age: <%= age %> <br>
</fieldset>
</script>
The function _.template($("#userTemplate").html(), user); can be called from within the complete callback function of the ajax, passing the data from the results to the function (user variable would be the data)
Using https://api.jquery.com/prop/
yourObj = [];
//now fill your object with your data
$row = $("td.yourClass")
$row.prop("dataObj", yourObj );
Related
I'm working on a Node.js app (it's a game). In this case, I have some code set up such that when a person visits the index and chooses a room, he gets redirected to the proper room.
Right now, it's being done like this with Express v2.5.8:
server.get("/room/:name/:roomId, function (req, res) {
game = ~databaseLookup~
res.render("board", { gameState : game.gameState });
}
Over in board.ejs I can access the gameState manner with code like this:
<% if (gameState) { %>
<h2>I have a game state!</h2>
<% } %>
Is there a way for me to import this into my JavaScript logic? I want to be able to do something like var gs = ~import ejs gameState~ and then be able to do whatever I want with it--access its variables, print it out to console for verification. Eventually, what I want to do with this gameState is to display the board properly, and to do that I'll need to do things like access the positions of the pieces and then display them properly on the screen.
Thanks!
You could directly inject the gameState variable into javascript on the page.
<% if (gameState) { %>
<h2>I have a game state!</h2>
<script>
var clientGameState = <%= gameState %>
</script>
<% } %>
Another option might be to make an AJAX call back to the server once the page has already loaded, return the gameState JSON, and set clientGameState to the JSON response.
You may also be interested in this: How can I share code between Node.js and the browser?
I had the same problem. I needed to use the data not for just rendering the page, but in my js script. Because the page is just string when rendered, you have to turn the data in a string, then parse it again in js. In my case my data was a JSON array, so:
<script>
var test = '<%- JSON.stringify(sampleJsonData) %>'; // test is now a valid js object
</script>
Single quotes are there to not be mixed with double-quotes of stringify. Also from ejs docs:
"<%- Outputs the unescaped value into the template"
The same can be done for arrays. Just concat the array then split again.
I feel that the below logic is better and it worked for me.
Assume the variable passed to the ejs page is uid, you can have the contents of the div tag or a h tag with the variable passed. You can access the contents of the div or h tag in the script and assign it to a variable.
code sample below : (in ejs)
<script type="text/javascript">
$(document).ready(function() {
var x = $("#uid").html();
alert(x); // now JS variable 'x' has the uid that's passed from the node backend.
});
</script>
<h2 style="display:none;" id="uid"><%=uid %></h2>
In the EJS template:
ex:- testing.ejs
<html>
<!-- content -->
<script>
// stringify the data passed from router to ejs (within the EJS template only)
var parsed_data = <%- JSON.stringify(data) %>
</script>
</html>
In the Server side script:
ex: Router.js
res.render('/testing', {
data: data // any data to be passed to ejs template
});
In the linked js (or jquery) script file:
ex:- script.js
In JavaScript:
console.log(parsed_data)
In JQuery:
$(document).ready(function(){
console.log(parsed_data)
});
Note:
1. user - instead of = in <% %> tag
2. you can't declare or use data passed from router to view directly into the linked javascript or jquery script file directly.
3. declare the <% %> in the EJS template only and use it any linked script file.
I'm not sure but I've found it to be the best practice to use passed data from router to view in a script file or script tag.
This works for me.
// bar chart data
var label = '<%- JSON.stringify(bowlers) %>';
var dataset = '<%- JSON.stringify(data) %>';
var barData = {
labels: JSON.parse(label),
datasets: JSON.parse(dataset)
}
You can assign backend js to front end ejs by making the backend js as a string.
<script>
var testVar = '<%= backEnd_Var%>';
</script>
This should work
res.render("board", { gameState : game.gameState });
in frontend js
const gameState = '<%- JSON.stringify(gameState) %>'
Well, in this case you can simply use input text to get data. It is easy and tested when you use it in firebase.
<input type="text" id="getID" style="display: none" value="<%=id%>">
I know this was answered a long time ago but thought I would add to it since I ran into a similar issue that required a different solution.
Essentially I was trying to access an EJS variable that was an array of JSON objects through javascript logic like so:
<script>
// obj is the ejs variable that contains JSON objects from the backend
var data = '<%= obj %>';
</script>
When I would then try and use forEach() on data I would get errors, which was because '<%= obj %>' provides a string, not an object.
To solve this:
<script>
var data = <%- obj %>;
</script>
After removing the string wrapping and changing to <%- (so as to not escape html going to the buffer) I could access the object and loop through it using forEach()
Suppose you are sending user data from the node server.
app.get("/home",isLoggedIn,(req,res)=>{
res.locals.pageTitle="Home"
res.locals.user=req.user
res.render("home.ejs");
})
And now you can use the 'user' variable in the ejs template. But to use the same value using client-side javascipt. You will have to pass the data to a variable in the tag.
Passing ejs variable to client-side variable:
<script>
let user= '<%- JSON.stringify(user) %>';
</script>
<script>home.js</script>
Now you can access the user variable at home.js
I have a controller which is passing the json object wrapped inside a model.
#RequestMapping("/template")
public String showTemplate(Model model) {
JSONObject obj = new JSONObject();
obj.put("equipmentID", "30584D277D6D4568B17EBB8917D0CB15");
model.addAttribute("template",obj);
return "templates";
}
I would like to use these values in my javascript. I am not able to do that. However, I can see display these values in HTML.
<head>
<script>
function test()
{
var temp = "${template}";
alert(temp); // The values are not displayed here
}
</script>
<body onload="test()">
<span th:text="${template}"> </span> //I can display the values here
<body>
I have also looked into this question How to get spring mvc controller model key value inside javascript? and tried both the options with or without quotes with no success.
I have also tried defining in HTML:
<input type="hidden" id="templates" value='${template}'/>
and using getElementById in my javascript with no success:
var template = document.getElementById("templates");
Using thymeleaf inlining you can use the below:
<script th:inline="javascript">
var message = [[${template}]];
alert(template);
</script>
There are additional ways to access server side variables depending on your use case refer to http://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#javascript-inlining for more information.
I got a code that replaces a string. Here is my HTML created by my PHP code.
...
foreach ($notes as $note) {
echo '<li><input name="noteTypeID" type="radio" class="noteTypeID" value="'.$note['NOTETYPEID'].'"></li>';
}
...
foreach (...) {
...
echo '<li class="getshrtcode">[srms_more_info id="'.$cnt.'" instanceID="'.$val_id.'" type="'.$val_type.'" noteCodeID="" planID=""]</li>';
...
}
my script is like this:
jQuery(document).ready(function(){
var noteTypeID = null;
var planID = null;
jQuery('.noteTypeID').click(function() {
noteTypeID = jQuery(this).val();
planID = prompt("Enter a Template planID value from axcelerate");
jQuery('.getshrtcode').each(function(){
jQuery(this).text(jQuery(this).text().replace('noteCodeID=""', 'noteCodeID="'+ noteTypeID +'"'));
jQuery(this).text(jQuery(this).text().replace('planID=""', 'planID="'+ planID +'"'));
});
});
});
the 1st change is fine but the next is not. I see that it can't re assign the .getshrtcode text because the planID and noteCodeID string have value. Is it possible to turn it noteCodeID="" planID="" again?
You are trying to set a non-DOM entity with jquery which is not possible. When you have a template engine to generate HTML, the template code gets executed and gives results before any javascript loads, so you cannot set template properties unless the template engine itself provides you a mechanism to do this.
If you really want the customer to specify a certain template plan ID to present him with something specific, you need to load your page through an AJAX call where you send a request to the server passing noteCodeID & planID and respond with the desired HTML that comes as a result of the custom template engine execution.
If you have custom attributes in your HTML that you want to set using jquery, then you can simply use attr function :
$('#foobar').attr('foo','bar');
I've never been good with JavaScript or jquery but my latest project has demanded that I get better. I'm trying to create a widget for a website. This widget uses ajax to access json data from another domain. This widget may have multiple instances on the same page, each with different settings.
I'm using JQuery to find all of the elements with a particular class which will identify where the widgets need to go. I'm using custom data- attributes to store the settings for each widget in what will be the container .
The problem I am having is this;
Because ajax request are asynchronous the results are coming in an effectively random order. The code Ihave so far is
<script>
var currentContainer;
$(document).ready(function(){
$($(".container")).each(function( index ){
currentContainer = this;
var url =
"http://example.com/json.php?iid="+$(this).data("owner_id")+
"&iid="+$(this).data("item_id")+
"&l="+$(this).data("layout")+
"&callback=?";
var request = $.get(url,function(data){
console.log(data)
display(data.oid,data.iid,data.l);
},"jsonp");
});
});
function display(oid,iid,l){
$(currentContainer).html("Owner Id = "+oid+" Item Id = "+iid+" Layout = "+l);
}
And in the body....
<div class="container" data-owner_id="George" data-item_id="car" data-layout="tidy">-</div>
<div class="container" data-owner_id="tim" data-item_id="computer" data-layout="allovertheplace">-</div>
<div class="container" data-owner_id="dee" data-item_id="hammer" data-layout="effingmess">-</div>
The result I get is random data in the last only. Any ideas much appreciated!
Don't use global variable in this case. Pass the currentContainer to the display function as an argument.
var currentContainer = this;
...
var request = $.get(url,function(data){
console.log(data)
display(currentContainer, data.oid,data.iid,data.l);
},"jsonp");
...
function display(currentcontainer, oid, iid, l) {
...
The problem is in the line:
$(currentContainer).html("Owner Id = "+oid+" Item Id = "+iid+" Layout = "+l);
When you loop through the divs with class container ($($(".container")).each), you're assigning currentContainer to the div you're working on. So at the end, currentContainerrefers to the last element with a class container.
In display, you want to select the div to act on using its data attribute. You can make this type of selection using jQuery's attribute selectors $("[attribute='val']")
I'm looking to use jQuery to determine if the current page has changed upstream, and if so, perform some action.
I want to do this by using jQuery selectors over the data returned by an AJAX call (for the purposes of this question, my "page has changed" metric will be "has the content of first <h1> changed").
Thus I find myself wanting to use jQuery selectors over the HTML returned by an AJAX get(). The "best" "solution" I've found thus far is appending the data to some hidden div, and using a selector over that, as below:
var old_title = $('h1').html();
$.get(url, function(data) {
$('#hidden_temporary_storage').append(data);
var new_title = $('#hidden_temporary_storage h1').html();
if (new_title !== old_title) {
do_something();
}
});
This feels so very wrong - I'd be nesting html / head / body tags, and there would be id collisions et cetera.
I have no control over the upstream page, so I can't just "get the data in a more convenient format" alas.
You can do:
var x = $('<div>'+data+'</div>').find('h1').html();
// use x as you like
i.e. you don't need to append the returned data to your page to be able to get properties and values from HTML elements defined within it. This way there would be no id collisions, multiple head/body tags etc.
I think your best bet here is to use an iFrame.
And then use jQuery on the content of that iFrame.
var old_title = $('h1').html();
$.get(url, function(data) {
$('<iframe id="tmpContent"></iframe>').appendTo("html");
$('#tmpContent').contents().find('html').html(data);
var new_title = $('#tmpContent').contents().find('h1').html();
if (new_title !== old_title) {
do_something();
}
$('#tmpContent').remove();
});