I am trying to load a JSON file into a JavaScript script for use in a Mustache script on a webpage. The JSON in a string loads correctly, but the same JSON in a file does not.
This works:
function renderHello() {
var json = JSON.parse('{"cloudy": "This applies to Snowflake.","classic": "This applies to SQL Server."}');
var template = document.getElementById("template").innerHTML;
var rendered = Mustache.render(template, json);
document.getElementById("target").innerHTML = rendered;
}
This does not work:
function renderHello() {
var json = JSON.parse('./abc.json');
var template = document.getElementById("template").innerHTML;
var rendered = Mustache.render(template, json);
document.getElementById("target").innerHTML = rendered;
}
Variations I've tried in abc.json:
{
"cloudy": "This applies to Snowflake.",
"classic": "This applies to SQL Server."
}
{"cloudy": "This applies to Snowflake.","classic": "This applies to SQL Server."}
I've unsuccessfully tried
var json = './abc.json';
var json = JSON.parse('./abc.json');
var json = JSON.stringify('./abc.json');
var json = JSON.parse(JSON.parse('./abc.json'));
var json = JSON.parse(JSON.stringify('./abc.json'));
Frequently an error like this is returned in the Chrome Developer Tools:
VM223:1 Uncaught SyntaxError: Unexpected token . in JSON at position 0
at JSON.parse (<anonymous>)
at renderHello (render.js:2)
at onload (docs.html:91)
I added these lines in the script to reveal the location of the website file that includes the Mustache template, so I knew where to locate abc.json:
var loc = window.location.pathname;
var dir = loc.substring(0, loc.lastIndexOf('/'));
console.log(dir)
And the file structure is now this:
directory
--file-with-mustache-script.html
--abc.json
This may not be relevant, but this is the Mustache script, which of course already works with the JSON as a string.
<body onload="renderHello()">
<div id="target">Loading...</div>
<script id="template" type="x-tmpl-mustache">
Hello {{ cloudy }}, {{ classic }}!
</script>
</body>
The website build tool I'm using does not support Node or Handlebars.
If it is relevant at all, the goal is to populate values from a JSON file in a product documentation website page to indicate which paragraphs apply to which product version.
You need to load the content of the file via "AJAX". You can't get the content like you are trying to do.
Something like this would do the job:
function renderHello() {
fetch('https://jsonplaceholder.typicode.com/users/3').then(r=>r.json())
.then(json=>{
// var template = document.getElementById("template").innerHTML;
// var rendered = Mustache.render(template, json);
document.getElementById("target").innerHTML = JSON.stringify(json,null,2);
})
}
renderHello();
<pre id="target"></pre>
As I don't have access to your abc.json file I used a publicly resource at http://typicode.com.
Related
This question was asked before but didn't get an answer. I have a php file which sends a json object to a javascript file which is supposed to render it with a template and display it on a div. The problem is, the function Mustache.to_html() returns empty. can anyone tell me what I am doing wrong. here's my code.
{
$(":button").click(function(){
var cat = $(this).attr("name");
$.get("trier.php",{input: cat}, function(data){
alert(data);
var template = $('#templabel').html();
console.log(template);
var html = Mustache.to_html(template, data);
console.log(html);
$('#feedback2').html(data);
});
});
}
The javascript sends the data to this php file which sends back a json object
{
if(isset($_GET['input'])){
$catt = $_GET['input'];
$info = "SELECT * FROM books WHERE (Category = '$catt')";
$information = mysqli_query($conn,$info);
$arraay = array();
while($r = mysqli_fetch_assoc($information)){
$arraay[] = $r;
}
$jason = json_encode($arraay);
$jason = '{"arraay":'.$jason."}";
echo $jason;
}
}
The javascript file will then send the json object rendered with the mustache template to the html file, to the tag with the id = "feedback2". But the display is raw json, not templated. and the second console.log after I apply the Mustache.to_html function returns an empty string. What am I doing wrong?
The output of the console.log for the template is
{{#arraay}}
<div>
<h2> {{Title}}</h2>
<p>{{Course}}</p>
<p>{{Category}}</p>
</div>
{{/arraay}}
and the alert for the data is
{"arraay":[{"Title":"Algorithms","Course":"CSI241","Category":"science"},{"Title":"Fluid dynamics","Course":"PHY345","Category":"science"}]}
Works for me:
var data = {"arraay":[{"Title":"Algorithms","Course":"CSI241","Category":"science"},{"Title":"Fluid dynamics","Course":"PHY345","Category":"science"}]};
var template = document.getElementById('template').innerHTML;
var html = Mustache.to_html(template, data);
document.getElementById('render').innerHTML = html;
<script src="https://cdnjs.cloudflare.com/ajax/libs/mustache.js/2.2.0/mustache.min.js"></script>
<template id="template">
{{#arraay}}
<div>
<h2> {{Title}}</h2>
<p>{{Course}}</p>
<p>{{Category}}</p>
</div>
{{/arraay}}
</template>
<div id="render">
</div>
In my project, I am keeping all html files in an organized way such that I can understand. For now, I am keeping them in template folder, something similar to as shown below:
template
--> Dashboard
--> left-content.html
--> right-content.html
--> Analytics
--> graph-section.html
--> profile
--> basic-profile.html
--> advanced-profile.html
I want these files to be compressed and get added as key-values of different js file with name templates.js
What I want is something like this:
templates.js
var templates = {
left-content: "html markup here",
right-content: "html markup here",
graph-section: "html markup here",
basic-profile: "html markup here",
advanced-profile: "html markup here"
}
So, later using any template plugin like lodash, I can render easily. For example:
var template = _.template(templates['left-content']);
var html = template({data: {/* some data here */}});
document.body.innerHTML = html;
And also, if I add any html files in future, the templates object in templates.js should get updated automatically.
Here is the code which I am using in my project. I hope this will be helpful.
var gulp = require('gulp');
var fs = require('fs');
var tap = require('gulp-tap');
var path = require('path');
var stringify = require('stringify-object');
// task without watch
gulp.task('template-build', function () {
var templates = {};
gulp.src('app/templates/*/*.html')
// Run a loop through all files in 'app/templates/*/*.html'
.pipe(tap(function (file, t) {
// For each file in the loop get "file name" and "file path"
var filePath = file.relative;
var fileNameWithExt = path.basename(filePath);
var fileName = fileNameWithExt.substring(0, fileNameWithExt.lastIndexOf("."));
templates[fileName] = fs.readFileSync('app/templates/' + filePath, 'utf8');
}))
.pipe(tap(function () {
// Append the above "file name" and "file path"
fs.writeFile('app/common/templates.js', "var templates = " + stringify(templates).replace(/[\n\r]*/g, ""));
}));
});
// this runs the `bundle-templates` task before starting the watch (initial bundle)
gulp.task('watch', ['template-build'], function () {
// now watch the templates and the js file and rebundle on change
gulp.watch(['app/templates/*/*.html'], ['template-build']);
});
Later in command prompt: (after visiting my project's directory)
gulp watch
BTW, I am still not be able to compress the html files. If someone has answer please feel free to edit this post.
I'm trying to display data from the xml file by first getting the content of the xml file and storing it in XML DOM. Once the DOM object is created it is then parsed. I used a for loop so as to get data from each child node of the parent node but somehow only the second node's data is showing.
This is the code where the error is:
xmlhttp.open("GET","company.xml", false); //sets the request for calling company.xml
xmlhttp.send(); //sends the request
xmlDoc = xmlhttp.responseXML; //sets and returns the content as XML DOM
//parsing the DOM object
var employeeCount = xmlDoc.getElementsByTagName("Employee");
for(i=0; i<employeeCount.length; i++)
{
document.getElementById("firstName").innerHTML = xmlDoc.getElementsByTagName("FirstName")[i].childNodes[0].nodeValue;
document.getElementById("lastName").innerHTML = xmlDoc.getElementsByTagName("LastName")[i].childNodes[0].nodeValue;
document.getElementById("contactNum").innerHTML = xmlDoc.getElementsByTagName("ContactNo")[i].childNodes[0].nodeValue;
}
The XML file:
<?xml version="1.0"?>
<Company>
<Employee category="technical">
<FirstName>Tanmay</FirstName>
<Nickname>Tania</Nickname>
<LastName>Patil</LastName>
<ContactNo>1234567890</ContactNo>
</Employee>
<Employee category="non-technical">
<FirstName>Taniya</FirstName>
<LastName>Mishra</LastName>
<ContactNo>1234667898</ContactNo>
</Employee>
</Company>
This the output:
How can i display the data from node [0] as well? Any suggestions will be appreciated. Thanks.
The problem is that you're overwriting data from previous Employee on every iteration :
for(i=0; i<employeeCount.length; i++)
{
document.getElementById("firstName").innerHTML = xmlDoc.getElementsByTagName("FirstName")[i].childNodes[0].nodeValue;
document.getElementById("lastName").innerHTML = xmlDoc.getElementsByTagName("LastName")[i].childNodes[0].nodeValue;
document.getElementById("contactNum").innerHTML = xmlDoc.getElementsByTagName("ContactNo")[i].childNodes[0].nodeValue;
}
That's why only the last Employee data remains in innerHTMLs in the end.
I have a XML file that is used by Flash as string resource
I would like my JS to use that XML as well: is there an easy way to read and parse external XML file in JS ?
like resources.xml that contains:
<resources locale="en">
<sizeUp>Size up</sizeUp>
<sizeDown>Size Down</sizeDown>
<clearSearch>Clear search</clearSearch>
<wouldYouLikeToReport>Would you like to report this user for abuse ?</wouldYouLikeToReport>
<yes>Yes</yes>
....
If you want to get every node and the text it contains, try this:
var xml;
xml = '<resources locale="en">';
xml += '<sizeUp>Size up</sizeUp>';
xml += '<sizeDown>Size Down</sizeDown>';
$(xml).children().each(function(index, elem) {
var $element = $(elem);
var text = $element.text();
console.log('elem is ');
console.log(elem);
console.log('text is ');
console.log(text);
});
The output will be:
elem is
sizeup
text is
Size up
elem is
sizedown
text is
Size Down
If you are looking for the contents of a specific tag, you could do:
console.log('sizeUp is ');
console.log($(xml).find('sizeUp').text());
I have a list of airport codes, names, and locations in an Excel Spreadsheet like the below:
+-------+----------------------------------------+-------------------+
| Code | Airport Name | Location |
+-------+----------------------------------------+-------------------+
| AUA | Queen Beatrix International Airport | Oranjestad, Aruba|
+-------+----------------------------------------+-------------------+
My Javascript is passed a 3 character string that should be an airline code. When that happens I need to find the code on the spreadsheet and return the Airport Name and Location.
Im thinking something like:
var code = "AUA";
console.log(getAirportInfo(code));
function getAirportInfo(code) {
// get information from spreadsheet
//format info (no help needed there)
return airportInfo;
}
Where the log would write out:
Oranjestad, Aruba (AUA): Queen Beatrix International Airport
What is the easiest method to get the data I need from the spreadsheet?
Extra Info:
The spreadsheet has over 17,000 entries
The function alluded to above may be called up to 8 times in row
I don't have to use an Excel Spreadsheet thats just what I have now
I will never need to edit the spreadsheet with my code
I did search around the web but everything I could find was much more complicated than what Im trying to do so it made it hard to understand what Im looking for.
Thank you for any help pointing me in the right direction.
I ended up using a tool at shancarter.com/data_converter to convert my flie to a JSON file and linked that to my page. Now I just loop through that JSON object to get what I need. This seemed like the simplest way for my particular needs.
I've used a plain text file(csv, or tsv both of which can be exported directly from Excel)
Loaded that into a string var via xmlhttprequest. Usually the browsers cache will stop having to download the file on each page load.
Then have a Regex parse out the values as needed.
All without using any third party....I can dig the code out if you wish.
Example:
you will need to have the data.txt file in the same web folder as this page, or update the paths...
<html>
<head>
<script>
var fileName = "data.txt";
var data = "";
req = new XMLHttpRequest();
req.open("GET", fileName, false);
req.addEventListener("readystatechange", function (e) {
data = req.responseText ;
});
req.send();
function getInfoByCode(c){
if( data == "" ){
return 'DataNotReady' ;
} else {
var rx = new RegExp( "^(" + c + ")\\s+\\|\\s+(.+)\\s+\\|\\s+\\s+(.+)\\|", 'm' ) ;
var values = data.match(rx,'m');
return { airport:values[2] , city:values[3] };
}
}
function clickButton(){
var e = document.getElementById("code");
var ret = getInfoByCode(e.value);
var res = document.getElementById("res");
res.innerText = "Airport:" + ret.airport + " in " + ret.city;
}
</script>
</head>
<body>
<input id="code" value="AUA">
<button onclick="clickButton();">Find</button>
<div id="res">
</div>
</body>
</html>