How to pass json file name to javascript function on button click? - javascript

I have a Javascript file that returns some HTML Content based on the content of a json file. In other words, in my file called "Resources" I have multiple json files and a single HTML File that contains multiple buttons. It can be more clear with an example, here is the HTML file:
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div class="cards">
<div class="card">
<img src="first.jpg" class="card_image">
<a href="javascript:showMenu()" class="animated-button"> <!--showMenu() is inside menu-card.js-->
<span></span>
<span></span>
<span></span>
<span></span>
<p>FIRST BUTTON</p>
</a>
</div>
<div class="card">
<img src="second.jpg" class="card_image">
<a href="javascript:showMenu()" class="animated-button"> <!--showMenu() is inside menu-card.js-->
<span></span>
<span></span>
<span></span>
<span></span>
<p>SECOND BUTTON</p>
</a>
</div>
</div>
<script type="text/javascript" src="first.json"></script>
<script type="text/javascript" src="second.json"></script>
<script type="text/javascript" src="menu_card.js"></script>
</body>
</html>
Here is first.json :
products =
`[
{
"name": "Shoes",
"description": "This are some shoes.",
"price": "180"
}
]`;
Here is second.json :
products =
`[
{
"name": "Hoodies",
"description": "This are some hoodies.",
"price": "90"
}
]`;
Finally, here is menu_card.js :
var storedMenu = JSON.parse(products);
//Some other stuff using storedMenu
Anyways, since I have multiple json files for different "categories" for my project and a SINGLE javascript file "menu_card.js" that must output some HTML content based on the json content, the problem is that I already have a lot of json files and they all have the same object name and I don't plan on changing it for every single file ( products = ... ). Is it possible to maybe pass the json file name from the href inside the HTML to the javascript function that will use it for the JSON.parse()?
I think I was clear enough with my issue, if something is unclear or not specified, I can easily edit the post. Thank you in advance!

Well you can change the script import like that
<script type="text/javascript" src="first.json">
fetch('/first.json')
.then(response => response.json())
.then( json => {
window.products = (window.products || []);
json.forEach( p => window.products.push(p) );
});
</script>
But files must be pure JSON
[
{
"name": "Hoodies",
"description": "This are some hoodies.",
"price": "90"
}
]
Rewrite them programmaticaly.
You could also rewrite then like below but it will change all the solution.
{
"name": "Hoodies",
"description": "This are some hoodies.",
"price": "90"
}
And so on... so everything will be available in window.products.
As it can be long to rewrite, you can do it for every file with something like
<script type="text/javascript" src="first.json">
Promise.all([ '/first.json', '/second.json']
.map( file => fetch(file).then( r => r.json() ) )
)
.then( allProducts => allProducts.flat() )
.then( allProducts => window.products = allProducts)
;
});
</script>

Related

Query and get data from an endpoint through the a search bar input in javascript

This endpoint http://vk-data:8003/v1/entity/ returns this:
[
{
"id": "country",
"url": "http://vk-data:8003/v1/entity/country",
"name": "Countries",
"description": "All the countries in the world"
},
{
"id": "data-site",
"url": "http://vl-data:8003/v1/entity/data-site",
"name": "World data storage",
"description": "A catalog of health data"
}
]
I want to write a function that allows user to access either data-site or country data through a search bar input.
How can I get my code to do that? Here's what I have so far.
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link rel="stylesheet" href="css/styles.css">
</head>
<body>
<button id="catalog" onclick="RetrieveCatalog()">Get Catalog</button>
<input type="text" placeholder="Search for User" onChange={(e) => RetrieveEntities(e.target.value)} className="input_search" />
<button onClick={fetchData} className="search_button">Search Github</button>
<script>
//fetch catalog function
function RetrieveCatalog(){
//http request
fetch("http://vk-data:8003/v1/entity/")
.then(function(data){
console.log(data)
return data.json()
})
.then(function(data){})
.catch(error => console.error(error))
}
//fetch catalog function
function RetrieveEntities(){
//http request
fetch("http://vk-data:8003/v1/entity/${entities}")
.then(function(data){
console.log(data)
return data.json()
})
.then(function(data){})
.catch(error => console.error(error))
}
</script>
</body>
</html>
I believe the issue is that you have got confused between JSX and HTML syntax.
There are a few areas where you have gotten mixed up between the two. Here are the places to fix.
In the <input> tag, change the onChange attribute to onchange. Also, surround the function with quotes ("") instead of curly braces ({}).
<input onchange="(e) => RetrieveEntities(e.target.value)" />
In the same <input> tag, change the className attribute to class.
<input class="input_search" />
In the <button> element, change the onClick attribute to onclick, as well as surrounding the value with quotes.
<button onclick="fetch"></button>
In the <button> tag, change className to class.
<button class="search_button"></button>
These changes in your HTML code should help solve the issue.

Searching JSON, but NOT case sensitive [duplicate]

This question already has answers here:
Case-insensitive search
(12 answers)
Closed 2 years ago.
So, the title pretty much says it all. I want to search a JSON, but try and not make it case sensitive. So here is my JSON file:
{ "Data" :
[
{"Name": "Widget", "Price": "25.00", "Quantity": "5" },
{"Name": "Thing", "Price": "15.00", "Quantity": "5" },
{"Name": "Doodad", "Price": "5.00", "Quantity": "10" }
]
}
Unfortunately for me, I have not coded in a long time so basically I wrote the JavaScript part of my code in the HTML file also. It's a bit muddled together:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div>
<form id="form1">
What product do you wish to find? <input name="name" type="text" size="20">
</form>
<button id="fetchUserDataBtn">Cauta</button>
</div>
<hr>
<div id="response"></div>
<script>
document.getElementById('fetchUserDataBtn').addEventListener('click', fetchUserData);
function fetchUserData(){
fetch('Vlad3.json')
.then(response => response.json())
.then(Data => {
let output = "Product list"
output += '<ul>';
var cauta1, cauta2;
cauta1=document.getElementById("form1");
cauta2=cauta1.elements["name"].value;
console.log(cauta2);
var nr=0;
Data.Data.forEach(function(Data) {
if(Data.Name==cauta2)
{nr++;
output += "Product "+Data.Name;
output+="<br>";
output+="Price "+Data.Price;
output+="<br>";
output+="Quantity "+Data.Quantity;
}
});
if(nr==0) {output+="We are sorry, this is not available";}
output += '</ul>'
document.getElementById("response").innerHTML = output;
});
}
</script>
</body>
</html>
Can I manage to add a function somewhere in here, so that when the user introduces "Thing" or "Widget" in the search area, it will find the product, even though it's not written exactly like in the JSON file?
Use .toLowerCase or .toUpperCase to do a case-insensitive compare.
if(Data.Name.toLowerCase()===cauta2.toLowerCase())

Replace jQuery with vanilla JS when parsing JSON, and other improvements

I would like get rid of jQuery for this simple task, but I don't know how to use vanilla JS to do the job. The page works fine, but I recognize that it is a mess, and I would like to improve the invisible, under the hood code.
I am a complete noob, I will try to explain what I've done but I need your help to simplify as much as possible and clean the code (one function only / alternative to javascript in "href" / everything else that comes to mind). And to get rid of a 88kB .js file just to call a function.
The web page contains two links that point to local Icecast streams.
When one selects a stream by clicking a link,
the common audio player loads the corresponing source URL (function changeStream());
the link is highligted and every other link returns to the default CSS (function changeBg());
the variable number is set to the correspondibg element number to allow title parsing;
the jQuery function getTitle() is executed.
Additional notes:
HTML IDs with "*-js" means that they are modified by a javascript function;
I may have mispelled something below, I have rewritten variables and other parts with easier to understand names;
Getting rid of jQuery is my priority, but other improvements are well accepted.
Thank you in advance
The webpage contains is
<!doctype html>
<html lang="en">
<head>[...]</head>
<body>
<div class="links">
<a id="/sourceA-js" class="sourceLink"
href="javascript:changeStream('/radio/sourceA'); changeBg('/sourceA-js'); var number=0; getTitle();">
<span class="sourceText">Stream A</span></a>
<a id="/sourceB-js" class="sourceLink"
href="javascript:changeStream('/radio/sourceB'); changeBg('/sourceB-js'); var number=1; getTitle();">
<span class="sourceText">Stream B</span></a>
</div>
<div id="currentTrackInfo">
<p>Track: <span id="currentTrackTitle-js">Please select a radio stream</span>
</p>
<audio id="radio-js" class="radioPlayer" controls>
<source src="" type="audio/mpeg">
</audio>
</div>
<script>
function changeBg (streamId) {
var boxes = document.getElementsByClassName('sourceLink'),
i = boxes.length;
while (i--) {
boxes[i].removeAttribute('style');
}
document.getElementById(streamid).setAttribute('style', 'color:grey;background-color:red;');
}
function changeStream (stream) {
document.getElementById('radio-js').pause();
document.getElementById('radio-js').setAttribute('src', stream);
document.getElementById('radio-js').load();
document.getElementById('radio-js').play();
}
</script>
<script src="/static/js/jquery.js"></script>
<script>
function getTitle () {
jQuery.get('status-json.xsl', {}, function (response) {
$('#currentTrackTitle-js').html(response.icestats.source[number]['title']);
document.title = response.icestats.source[number]['title'];
});
}
gettitle();
setInterval(gettitle, 15000);
</script>
</body>
</html>
The parsed file, status-json.xsl, contains
{
"icestats": {
"admin": "mail",
"host": "domain",
"location": "name",
"server_id": "version",
"server_start": "humandate",
"server_start_iso8601": "computerdate",
"source": [
{
"audio_info": "bitrate=320",
"bitrate": 320,
"genre": "Jazz",
"listener_peak": 2,
"listeners": 1,
"listenurl": "address",
"server_description": "streamdescription",
"server_name": "streamname",
"server_type": "audio/mpeg",
"server_url": "/radio/jazz",
"stream_start": "humandate",
"stream_start_iso8601": "computerdate",
"title": "author - title",
"dummy": null
},
{
"audio_info": "bitrate=320",
"bitrate": 320,
"genre": "Jazz",
"listener_peak": 2,
"listeners": 1,
"listenurl": "address",
"server_description": "streamdescription",
"server_name": "streamname",
"server_type": "audio/mpeg",
"server_url": "/radio/jazz",
"stream_start": "humandate",
"stream_start_iso8601": "computerdate",
"title": "author - title",
"dummy": null
}
]
}
}
This appears to be the only jQuery code that you want to replace:
jQuery.get("status-json.xsl", {}, function(response) {
$('#currentTrackTitle-js').html(response.icestats.source[number]['title']);
document.title = response.icestats.source[number]['title'];
});
Vanilla JavaScript equivalent to jQuery.get() is fetch. This will read JSON string from file and convert it to a JavaScript object:
fetch("status-json.xsl")
.then(response => {
// parse JSON from 'status-json.xsl' file
return response.json();
})
.then(status => {
// perform your app logic here
});
This jQuery code:
$('#currentTrackTitle-js').html(response.icestats.source[number]['title']);
can be replaced with this vanilla JavaScript:
const currTitle = document.getElementById('currentTrackTitle-js');
currTitle.innerHTML = status[number]['title'];
Putting it all together:
const currTitle = document.getElementById('currentTrackTitle-js');
fetch("status-json.xsl")
.then(response => {
return response.json();
})
.then(status => {
currTitle.innerHTML = status.icestats.source[number]['title'];
document.title = status.icestats.source[number]['title'];
});

Populating HTML with JSON data using jQuery

I am trying to dynamically create a list of applicants in my HTML. I have a list of applicant saved in JSON format that I am reading in. I have an HTML template of the applicant "tile" that I read in, populate and then append to the page for each applicant.
My template:
<div>
<div class="name"></div>
<div class="age"></div>
<div class="gender"></div>
<div class="email"><i class="fa fa-envelope"></i></div>
</div>
My JSON data:
{
"applicants" : [
{
"name" : "John Smith",
"email" : "email#gmail.com",
"gender" : "Male",
"age" : "22"
}
]
}
My jQuery:
$.get("applicants.json", function(json) {
json.applicants.forEach(function(applicant) {
var newApplicant = $(templates).find("#applicant").html();
$(newApplicant).find(".name").append(applicant.name);
$(newApplicant).find(".email").append(applicant.email);
$(newApplicant).find(".gender").append(applicant.gender);
$(newApplicant).find(".age").append(applicant.age);
$(newApplicant).appendTo(".applicant-list");
});
});
After running this code, I am just getting the template back without the JSON information.
I have tried placing a console.log() after appending applicant.name but there is still no change to newApplicant.
Something else I tried was console.log($(newApplicant).find(".name").append(applicant.name).html()); which showed me that the .name is being populated but those changes are not persisting.
Can anyone see what I am doing wrong?
Thanks.
I am not sure if forEach would be a right one. You can use jQuery's $.each function to loop in an array with this being referred as the current iterated object:
$.each(json.applicants, function () {
var newApplicant = $("body").find("#applicant > div").clone();
newApplicant.find(".name").append(this.name);
newApplicant.find(".email").append(this.email);
newApplicant.find(".gender").append(this.gender);
newApplicant.find(".age").append(this.age);
$(newApplicant).appendTo(".applicant-list");
});
Snippet
$(function () {
json = {
"applicants" : [
{
"name" : "Nicholas Robinson",
"email" : "ntrpilot#gmail.com",
"gender" : "Male",
"age" : "22"
}
]
};
$.each(json.applicants, function () {
var newApplicant = $("body").find("#applicant > div").clone();
newApplicant.find(".name").append(this.name);
newApplicant.find(".email").append(this.email);
newApplicant.find(".gender").append(this.gender);
newApplicant.find(".age").append(this.age);
$(newApplicant).appendTo(".applicant-list");
});
});
<script src="https://code.jquery.com/jquery-1.9.1.js"></script>
<div id="applicant">
<div>
<div class="name"></div>
<div class="age"></div>
<div class="gender"></div>
<div class="email"><i class="fa fa-envelope"></i></div>
</div>
</div>
<div class="applicant-list"></div>
In the question you omitted two HTML elements that instead you mention in the jQuery code, so according to the latter, and correct me if I'm wrong, the HTML should look like that
<div class="applicant-list">
<div class="applicant">
<div class="name"></div>
<div class="age"></div>
<div class="gender"></div>
<div class="email"><i class="fa fa-envelope"></i></div>
</div>
</div>
Then, in the jQuery you should either use your $.get() function and then parse or use instead $.getJSON()
$.getJSON("applicants.json", function(json) {
json.applicants.forEach(function(applicant) {
var newApplicant = $('body').find(".applicant").clone();
$(newApplicant).find(".name").append(applicant.name);
$(newApplicant).find(".email").append(applicant.email);
$(newApplicant).find(".gender").append(applicant.gender);
$(newApplicant).find(".age").append(applicant.age);
$(newApplicant).appendTo(".applicant-list");
});
});

How to create a Mustache template for JSON data with nested objects?

I have this JSON data
[
{
"item":{
"name":"some name",
"description":" someDescription ",
"price":"6",
"image_url":"url"
},
"options":[
]
},
{
"item":{
"name":"some name",
"description":" someDescription ",
"price":"6",
"image_url":"url"
},
"options":[
]
}
]
and my code is
<script id="itemtpl" type="text/template">
{{#items}}
{{#item}}
<div class ="item">
<img src = "{{image_url}} alt="Photo of {{menu_item_name}}"/>
<h3>{{menu_item_name}}</h3>
<h4>{{menu_item_price}}</h4>
<p>{{menu_item_description}}</p>
</div>
{{/#item}}
{{/items}}
</script>
<script type ="text/javascript">
$(function(){
$.getJSON('fullmenu.json', function(data) {
var template = $('#itemtpl').html();
var html = Mustache.to_html(template, data);
$('#menu').html(html);
});//getJSON
});//function
</script>
I am using JavaScript and Mustache Templates to display all the items with its name, description and picture. But I am having trouble accessing through nested arrays. How do I retrieve these nested values?
If you want to iterate over a top-level array you should refer it as {{#.}} .. {{./}}
Also you have some typos, look, that's how your template will work:
{{#.}}
{{#item}}
<div class ="item">
<img src = "{{image_url}} alt="Photo of {{name}}"/>
<h3>{{name}}</h3>
<h4>{{price}}</h4>
<p>{{description}}</p>
</div>
{{/item}}
{{/.}}

Categories