Ruby and Javascript: passing a Ruby array as a Javascript variable - javascript

I'm trying to dynamically draw a Google Map and place a marker on it. In my controller, I assemble an array containing the name of the businesss, latitude, longitude and a z-index.
I have an array in Ruby that is available to my Rails view:
#locations = [["Location One",36.0552,-114.928,1]]
When I try to use that array in some Javascript:
var loc = <%= #locations %>
I see this in view source:
var loc = [["Location One",36.0552,-114.928,1]]
In order for the map to display the variable needs to read like:
var loc = [['Location One',36.0552,-114.928,1]]
With the quotes intact around the first element of the array. If I hard code that last line into the Javascript the map renders correctly. It really seems to be the quot; tags that are messing things up.
There will be more than one location on the map so I thought an array of arrays would be the best way to get the needed data into my view.
How can I accomplish this? Thanks.

Edit Corrected following DNNX's comment.
I think you need to convert it to json (a subset of JavaScript) before rendering:
require "json"
...
var loc = <%= #locations.to_json.html_safe %>

you need to use html_safe to prevent the escape the quote

Related

using Javascript to get unique XML child nodes

I'm a noob trying to build a map for my Com. Prog. class with the Google Maps API.
I have data that I want to output as markers and infowindows.
I used Codeigniter to output an XML from my database. (data modified for privacy)
<markers>
<item0>
<city>Boston</city>
<latitude>0.01111</longitude>
<longitude>1.2345</longitude>
</item0>
<item1>
<city>Los Angeles</city>
<latitude>9.99999</latitude>
<longitude>2.00011</longitude>
</item1>
</markers>
Now I'm trying to use Javascript to get all the child nodes of each "item" tag.
My callback function:
var xml = data.responseXML;
var items = xml.documentElement.getElementsByTagName("markers");
// for loop iterates through each the child nodes of the "item" tags.
Array.prototype.forEach.call(items, function(markerElem) {
var city = nodeValue(markersElem.children.item[0]);
var point = new google.maps.LatLng(
parseFloat(nodeValue(markersElem.children.item[1])),
parseFloat(nodeValue(markersElem.children.item[2])));
});
The main problem (I believe) is that the "item" tags each contain a unique number, so I can't call them with the getElementsByTagName method.
I've tried modifying the items variable to get the children nodes of the "markers" tag:
var items = xml.documentElement.getElementsByTagName("markers").children;
But the console outputs an error where the items variable is now undefined.
I've also tried to modify the XML file, but I can only seem to output XML through Codeigniter's built-in helper. Maybe there is a way to create a DOM document in PHP 7 that I don't know about?
It will be much easier if you convert XML in your controller with the simplexml_load_string() to a PHP array or object and then use the json_encode() to convert it to JSON format, so it will be much easier to work with this JSON array or object in JS code.
In your controller do this and send it to your view:
json_encode(simplexml_load_string(your XML here), JSON_UNESCAPED_UNICODE);
I would suggest that you would use XPath for that it will allow you to pull all the element under a cetrain path which you can then iterate over as normal.

Serliazing Java HashMap to JSON using Jackson ObjectMapper

I am developing a Spring Boot MVC application that uses Thymeleaf templates on the front end.
I am trying to bind a HashMap from my MVC model to a JavaScript variable in one of my Thymeleaf templates. This is what has been done so far: -
In my MVC controller class, I created a HashMap that represents user skills organised into categories. The Skill class is a data object containing name and id properties: -
Map<String, List<Skill>> skillsMap = new HashMap();
I populated this map with all the category and skill information and then added it to my Model: -
model.addAttribute("skillsMap", skillsMap);
On my Thymeleaf template in a script section, I am attempting to bind this HashMap to a variable. As a second step I then attempt to retrieve one of the lists from the map and assign to a second variable: -
var skillsMapMap = [[${skillsMap}]];
var adminList = skillsMapMap.get('Admin');
When I debugged this, I could see that the HashMap was being read and an attempt was being made to bind it to my JavaScript variable: -
var skillsMapMap = {Languages=[Python, SQL, PL/SQL, Java], Databases=[MySQL, Oracle, Mongo], Editors=[Word, TextPad, Notepad]};
This looked good at first glance and I could see that it contained all my data, but it was throwing the following error: -
Uncaught Syntax Error: invalid shorthand property initializer
Having researched this, I realized that this error was caused because Java does not by default serialize the map in valid JSON format and so the attempted bind to a JavaScript variable failed. So, instead of just adding the HashMap straight to the Model as in step 2, I added some code to use Jackson to convert it into a JSON String first: -
//Populate the map with all required data then....
String objectMapper = null;
try {
objectMapper = new ObjectMapper().writeValueAsString(skillsMap);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
model.addAttribute("skillsMap", objectMapper);```
This time When I attempt to bind this to my JavaScript variable, the object looks like this when I debug in my browser: -
var skillsMapJson = {"Languages_OD":[{"id":66,"name":"SQL"},{"id":67,"name":"PL/SQL"}], etc, etc};
The JSON now looks valid, but all the quotes are escaped and it now throws a different exception: -
```Uncaught SyntaxError: Unexpected token &```
I feel that if the JSON string contained actual quotes instead of " the Map would successfully bind to my variable. I would appreciate any advice as to how to deal with this. Many thanks for reading.
EDIT: Screenshot of error added below: -
I did eventually get round this problem and so am offering a solution in case it helps anyone else. However, I feel that the solution is a bit 'hacky' and so would welcome any further answers that improve on this or offer a more elegant solution.
The problem was in the way I was trying to retrieve my map from the Model and assign to a JavaScript variable. Initially, I was trying this: -
var skillsMapRawString = [[${skillsMapJson}]];
The trouble is that this way of referencing skillsMapJson forces JavaScript to treat it as an Object and it cannot deal with the encoding issue described in the original post when attempting to deserialize it into JSON. The above line therefore threw the exception "unexpected token &".
By adding single quotes around the object reference, JavaScript is forced to treat skillsMapJson as a String and not an object: -
var skillsMapRawString = '[[${skillsMapJson}]]';
The above variable assignment now works successfully, but we still have the problem that it contains encoded quotes which prevent it being parsed to a JSON Object. This is where it feels like a bit of a hack, because I got round this by doing a global replace on the String: -
var skillsMapJSONString = skillsMapRawString.replace(/"/g, "\"");
Having replaced the encoded sections that were causing problems before, the String can now be parsed as JSON: -
var skillsMapParsed = JSON.parse(skillsMapJSONString);
And finally, I have my map of lists successfully assigned to a JavaScript variable! :)
Symbols """ and similar are HTML escapes. So your info is HTML escaped. You can unescape it back by using class org.apache.commons.text.StringEscapeUtils from the library apache.commons/commons-text. The info found at: How to unescape HTML character entities in Java?

Proper way to use split-command and ","

i have following problem:
i have an array with a lot of data retrieved from mssql and hand it over to a jsp, i will simplify it in a example:
("test","1","test2","2")
those are 4 fields. With split(",") i seperate the 4 fields, so that i can take each value and assign them to html-objects.
Now through a coincidence i found out, that if the Array is filled as follows:
("test","1","test,2","2")
where "test,2" is one text, the split command seperates the 4 values to 5 values. Is there any alternative or way so that the split command ignores the "," that are part of a string of a field?
Greetings,
Kevin
Update:
Sorry for the missunderstandings guys here i tried to simplify the code as far as i can:
<script>
var jsArray = [];
<%
// Getting ArrayList from a request Attribute with a lot of data rows
ArrayList arrayList = (ArrayList)request.getAttribute("DSList");
for(int i=0;i<arrayList.size();i++){
%>
// Pushing each row to javascript array
jsArray.push("<%= ((ArrayList)arrayList.get(i))%>");
<%
}%>
// thats the split command that gets one line of the whole dataset
Stringarray = jsArray[x].substr(1,jsArray[x].length-2).split(","); // where x is the current record
</script>
now i can simply call each filed with
Stringarray[n] //where n is the field number
thats how the code looks like, the problem now is that if in one of the Strings in any record line is a "," then the split command obviously would give back the wrong field count. I hope now it's more clear what i mean
You can use non-greedy regex to filter out value inside "" and then remove "" from the words using array#map.
var string = '("test","1","test,2","2")';
var array = string.match(/"(.*?)"/g).map(function(item){
return item.replace(/"/g,'');
});
console.log(array);
Essentially, you have a backend data source and a front-end consumer. It just so happens that they reside on the same page, since you're using JSP to generate the page and the data. So treat it like a synchronous API, just embedded into the page.
How would you transmit data between and API and JavaScript? JSON.
So, stringify your result array into a JSON string and embed that into the JSP page, then JSON.parse() that in JavaScript and iterate as you would any other array.
Since I don't see your JSP code, I can't propose a more specific solution that what's linked here for creating JSON in JSP: how to add a list of string into json object in jsp? and Creating a json object in jsp and using it with JQuery

Accessing Rails child objects within Javascript

I'm very new to rails, so please bear with me. I haven't quite grasped all the "magic" just yet.
Basically I need to access Location objects in Javascript, which all contain 0-N Coordinates. I'm pretty sure the model is set up right, with each Coordinate having a location_id.
I managed to get a parsed JSON of Location objects using the following method: I put
def index
#locations = Location.all.to_json
end
in the controller, and accessed this in the view with
var theLocations = <%= #locations.html_safe %>;
when I show this variable in the log, however, it doesn't show the Coordinates, which kind of makes sense. Thing is, I was planning to iterate over all the Locations and for each one create a javascript var with the relevant coordinates. These vars would then be passed to Google maps as objects.
Basically I was planning on doing something like (pseudocode):
for(Location l in Locations){
get all Coordinate objects within Location
for(Coordinate c: Coordinates);
var myObject = new google.maps.LatLng(c.X, c.Y),
add myObject to list for this location.
}
}
I'm just not sure how to approach this. How can I get a reference to the Coordinates within the Locations?
The quick and dirty answer is to pass a parameter in your to_json call:
#locations = Location.all.to_json(:include => :coordinate)
You may also want to consider creating a custom JSON structure by overriding as_json and rendering the objects as JSON after that.

Ruby & Rails - Convert String to Proc

I'm in the following situation. The current url looks like the following:
/categories/Art
And I'm using name = location.pathname.split('/')[2] in order to grab the Art portion of the URL. Then, I send an AJAX the following path back to the controller: http://localhost:3000/sort?sortMethod=name&category=name or date, whichever link is clicked on.
Now in my controller I can use sort = params[:category] to get the string name, yet what I'd like to do with this string is sort an array by it. #categories is an array of objects and I'd like to call .sort_by(&:sort) yet it doesn't recognize the string value of sort = name. So now I'd like to convert this string into a proc in order to sort the array. Anyone know how I accomplish this?
Any help is greatly appreciated!
Convert it to a symbol first and then use Symbol#to_proc:
#categories.sort_by(&sort.to_sym)
However be sure that the users can't call anything malicious on your objects like:
http://localhost:3000/sort?sortMethod=destroy
One way of protecting yourself is to use attribute_accessible definitions in your model and then do
#categories.sort_by(&sort.to_sym) if Category.accessible_attributes.include? sort.to_sym
The problem is not entirely clear, so you may need to adjust the following solution. However, the basic idea is taht it's possible to do something like:
Category.all.sort_by {|category| category.method(params[:category]).call }
Also, the "Art" portion of your url is available in Rails' params hash as params[:action], so you don't have to do location.pathname.split('/')[2].

Categories