How to read object properly in JavaScript - javascript

I am new to programming and recently began learning Javascript, I have a problem that appeared in few exercises that I made. I searched the site for more information but have not found a solution for my problem. I apologize in advance for my bad english and if this is not the right place or the right way to ask this question because this is my first post in Stackoverflow.
Currently practicing HTML templates. Assuming that the code is correct, I'm not sure where I'm wrong. Loading code into the browser and Handlebars gives me an error: "Error: You must pass a string or Handlebars AST to Handlebars.compile. You passed undefined". I tried to debug and saw that when I tried to take a value from date object it gives back undefined. In previous exercise had a similar problem in which I tried to read JSON object and did not manage to parse it and returned again undefined. Can you help me, I am stuck on this problem for some time.
var data = {
animals: [{
name: 'Lion',
url: 'https://susanmcmovies.files.wordpress.com/2014/12/the-lion-king-wallpaper-the-lion-king-2-simbas-pride-4685023-1024-768.jpg'
}, {
name: 'Turtle',
url: 'http://www.enkivillage.com/s/upload/images/a231e4349b9e3f28c740d802d4565eaf.jpg'
}, {
name: 'Dog'
}, {
name: 'Cat',
url: 'http://i.imgur.com/Ruuef.jpg'
}, {
name: 'Dog Again'
}]
}
window.onload = function() {
var htmlTemplate = document.getElementsByClassName('container-template').innerHTML;
var template = Handlebars.compile(htmlTemplate);
for (let x of data.animals) {
if (x.hasOwnProperty('url')) { //x.url
x.hasUrl = true;
} else {
x.hasUrl = false;
}
}
document.getElementsByClassName('container').innerHTML = template(data);
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Animals & Batman</title>
</head>
<body>
<div class="container">
</div>
<script class="container-template" type="text/x-handlebars-template">
<h1>Animals</h1>
{{#each animals}}
{{#if hasUrl}}
<li>
See a {{name}}
</li>
{{else}}
<li>
No link for {{name}}, here is Batman!
</li>
{{/if}}
{{/each}}
</script>
<script src="../handlebars-v4.0.5.js" charset="utf-8"></script>
<script src="../jquery-3.1.0.js" charset="utf-8"></script>
<script src="./main.js" charset="utf-8"></script>
</body>
</html>

document.getElementsByClassName returns an array of elements, not a single one - since multiple elements on a page can have the same class.
What you probably want is to use the id instead of class:
<script id="container-template" type="text/x-handlebars-template">
var htmlTemplate = document.getElementById('container-template').innerHTML;

Related

How can I access a specific element within the Our World in Data COVID-19 Master Vaccinations JSON File?

I'm relatively new to coding and am trying to access a specific element within COVID Vaccine JSON file created by Our World in Data, but I'm having a hard time with the syntax of my code/the structure of the JSON file.
I've successfully consumed the data from the JSON file (it's appearing in my inspector of the HTML page), but now I want to be able to call out a specific data field to display it in my HTML.
For example, I wanted the total number of people vaccinated in the United States on 04-07-2021 and was trying to the code below, but received Cannot read property 'United States of undefined as an error. Also, for context on my approach, I haven't learned how to use one of the frameworks yet, so I'm doing some DOM manipulation to get the data to display in the HTML.
//110 is the total number of days that US vaccination data has been tracked, according to my math
var settings = {
"url": "https://raw.githubusercontent.com/owid/covid-19-data/master/public/data/vaccinations/vaccinations.json",
"method": "GET",
"timeout": 0,
$.ajax(settings).done(function (response) {
JSON.parse(response);
console.log(response);
var content = response["country"]["United States"]["date"][110];
document.getElementById("admin").innerHTML = response;
});
I also tried the following, which is also throwing errors:
var settings = {
"url": "https://raw.githubusercontent.com/owid/covid-19-data/master/public/data/vaccinations/vaccinations.json",
"method": "GET",
"timeout": 0,
};
$.ajax(settings).done(function (response) {
JSON.parse(response);
console.log(response);
var content = response.country[264].data.date[110]"
document.getElementById("admin").innerHTML = response;
});
This is my first time writing code for a GET API call, so any and all feedback are welcome! For reference, the raw JSON file can be found here and their GitHub can be found here (file is named vaccinations.json). My HTML is also included below for additional context. Thanks in advance!
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vaccine Visualization</title>
<!--enabled with jQuery-->
<<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<script src="vaccines.js"></script>
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Archivo:wght#400;600;800&family=Staatliches&display=swap"
rel="stylesheet">
<link href="vaccines-stylesheet.css" rel="stylesheet">
<style></style>
</head>
<body>
<div class="triangle">
<div class="content">
<h1 class="header"> International COVID Vaccine Rollout </h1>
<h2 class="subheader">PERCENT COMPLETE BY COUNTRY</h2>
</div>
</div>
<div class="triangle2"></div>
<div class="top-five-widget">
<h2 class="top-five-title"> COVID Vaccine Distribution:<br>Top Five Countries</h2>
<p>Total Vaccines Administered:</p>
<span id="admin"></span>
</div>
<script src="vaccines.js"></script>
</body>
</html>
This should display the number of people vaccinated on '2021-04-07'
var settings = {
"url": "https://raw.githubusercontent.com/owid/covid-19-data/master/public/data/vaccinations/vaccinations.json",
"method": "GET",
"timeout": 0,
};
$.ajax(settings).done(function (response) {
const USA = JSON.parse(response).find((data) => data.country === 'United States');
const peopleVaccinated = USA.data.find((d) => d.date === '2021-04-07').people_vaccinated;
document.getElementById("admin").innerHTML = peopleVaccinated;
});
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vaccine Visualization</title>
<!--enabled with jQuery-->
<<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<script src="vaccines.js"></script>
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Archivo:wght#400;600;800&family=Staatliches&display=swap"
rel="stylesheet">
<link href="vaccines-stylesheet.css" rel="stylesheet">
<style></style>
</head>
<body>
<div class="triangle">
<div class="content">
<h1 class="header"> International COVID Vaccine Rollout </h1>
<h2 class="subheader">PERCENT COMPLETE BY COUNTRY</h2>
</div>
</div>
<div class="triangle2"></div>
<div class="top-five-widget">
<h2 class="top-five-title"> COVID Vaccine Distribution:<br>Top Five Countries</h2>
<p>Total Vaccines Administered:</p>
<span id="admin"></span>
</div>
<script src="vaccines.js"></script>
</body>
Explanation
The response is an array of objects, each object has a key of country.
So when I do a .find, it loops through the array looking for an object with a key of country equal to "United States" and saves it in a variable USA.
Which is what this line is doing.
const USA = JSON.parse(response)
.find((data) => data.country === 'United States');
USA itself is another object that has a key of data which is an array of objects.
So I do another .find on USA.data for the object with a key of date that is equal to '2021-04-07', and when it finds it we immediately chain .people_vaccinated to it.
That is this line:
const peopleVaccinated = USA.data
.find((d) => d.date === '2021-04-07').people_vaccinated;
The rest should make sense to you.
Consider checking out How can I access and process nested objects, arrays, or JSON? Like someone suggested in the comments.

Passing variable to Custom Svelte Web Component

I have created simple Custom Web Component using Svelte. It has been compiled and seems it should work well, but there is the difficulty. I'm trying to pass into prop some variable, but getting undefined all the time, but if I'm passing some string
Result.svelte component
<svelte:options tag="svelte-result" />
<script>
export let result = {metadata: {}, transfers: []};
export let string = 'no string';
</script>
<div class="result__wrapper">
{string}
<div class="result__metadata">
<div>{result.metadata.offset}</div>
<div>{result.metadata.limit}</div>
<div>{result.metadata.total}</div>
</div>
</div>
When it copiled I'm using it like
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Svelte test</title>
<script defer src="/svelte/wapi-client/svelte-component.js"></script>
</head>
<body>
<div id="test"></div>
</body>
<script>
const data = {
metadata: {
limit: 20,
offset: 0,
total: 311301
},
transfers: [
{
amount: "7.95",
identifier: "9cd9901f-44a5-4436-9aef-880354bbe2e4"
}
]
};
document.getElementById('test').innerHTML = `
<svelte-result string="works" result=${data}></svelte-result>`;
</script>
</html>
data variable not passed to component, but string passed and shown correctly... What Am I doing wrong? How can I pass data variable into component ?
You can't pass objects as attributes to custom elements. You need to stringify your object before passing it.
index.html
...
document.getElementById('test').innerHTML = `
<svelte-result string="works" result=${JSON.stringify(data)}></svelte-result>`;
...
Foo.svelte
<svelte:options tag="svelte-result" />
<script>
export let result = {metadata: {}, transfers: []};
export let string = 'no string';
$: _result = typeof result === 'string' ? JSON.parse(result) : result;
</script>
<div class="result__wrapper">
{string}
<div class="result__metadata">
<div>{_result.metadata.offset}</div>
<div>{_result.metadata.limit}</div>
<div>{_result.metadata.total}</div>
</div>
</div>
As an alternative to using JSON.stringify to pass the data to the component, you can pass it as a property rather than as an attribute — in other words instead of this...
document.getElementById('test').innerHTML = `
<svelte-result string="works" result=${data}></svelte-result>`;
...you do this:
document.getElementById('test').innerHTML = `
<svelte-result string="works"></svelte-result>`;
document.querySelector('svelte-result').result = data;
Not ideal, of course, since it means that you have to accommodate the initial undefined state and the post-initialisation state once result has been passed through, but web components are a bit awkward like that.

Polymer 1.x: How to format a number while typing it into paper-input?

TL;DR: I want my numbers to look like 1,500 (not 1500) when entering it in an <input (actually <paper-input or even <iron-input?) form field. Similar to this example except using Polymer only and not AngularJS.
I want to format a number in paper-input (using, say, Numeral.js) while it's being entered by the user. I don't really know where to begin or what to try. I want to access the numeric value in the JS, but I want the user to be able to see the nicely formatted (string) version while entering it.
Is this even possible? Or perhaps I might need a separate display field? But then that would defeat the purpose of the paper-elements from a UX standpoint? Any help?
Also, note per the second comment on this SO question:
Worth noting that Number.prototype.toLocaleString still does not work in Safari, in 2016. Instead of actually formatting the number, it just returns it, no error thrown. Having the biggest facepalm today as a result of that... #goodworkApple – aendrew
Here is the jsbin. ... http://jsbin.com/wosoxohixa/1/edit?html,output
http://jsbin.com/wosoxohixa/1/edit?html,output
<!doctype html>
<head>
<meta charset="utf-8">
<base href="https://polygit.org/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link href="polymer/polymer.html" rel="import">
<link href="paper-input/paper-input.html" rel="import">
<script src="//cdnjs.cloudflare.com/ajax/libs/numeral.js/1.4.5/numeral.min.js"></script>
</head>
<body>
<dom-module id="x-element">
<template>
<style></style>
<paper-input value="{{num}}"></paper-input>
</template>
<script>
(function(){
Polymer({
is: "x-element",
properties: {
num: {
type: Number,
value: function() {
return numeral(1500).format('0,0');
},
},
},
});
})();
</script>
</dom-module>
<x-element></x-element>
</body>
Based on the answer from #akc42, I constructed the following working jsBin. ... http://jsbin.com/zunezojuzu/1/edit?html,console,output
http://jsbin.com/zunezojuzu/1/edit?html,console,output
<!doctype html>
<head>
<meta charset="utf-8">
<base href="https://polygit.org/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link href="polymer/polymer.html" rel="import">
<link href="paper-input/paper-input.html" rel="import">
<script src="//cdnjs.cloudflare.com/ajax/libs/numeral.js/1.4.5/numeral.min.js"></script>
</head>
<body>
<dom-module id="x-element">
<template>
<style></style>
<paper-input value="{{num}}"></paper-input>
</template>
<script>
(function(){
Polymer({
is: "x-element",
properties: {
num: {
type: String,
observer: '_numChanged',
},
},
attached: function() {
this.numBeingChanged = false;
},
_numChanged: function(num) {
console.log('num', num);
if (!this.numBeingChanged) {
this.numBeingChanged = true; //prevent recursion
var x = num.replace(/\D/g,'')
x = parseInt(x);
console.log('x', x);
this.set('num', numeral(x).format('0,0'));
this.numBeingChanged = false;
}
}
});
})();
</script>
</dom-module>
<x-element></x-element>
</body>
I do something similar with a datepicker based around paper input. Put an observer on the num property, and it will get called as every new character arrives.
You also need to be careful with validation as you may end up trying to validate 1,0 if that is the way the user has typed it in. (assuming he may type with or without your formatiing

JSON.stringify not working in IE10

I am trying to parse some form data to produce JSON data to send in an ajax request. The following HTML is an oversimplified version of my code. I'm using APS.Net MVC4 and my rendered view produces the following HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>Index</title>
<link href="/Content/site.css" rel="stylesheet"/>
<script src="/Scripts/modernizr-2.6.2.js"></script>
</head>
<body>
<div class="test-class" data-my-attribute="1"></div>
<div class="test-class" data-my-attribute="2"></div>
<div class="test-class" data-my-attribute="3"></div>
<script src="/Scripts/jquery-1.8.2.js"></script>
<script type="text/javascript">
$(function () {
jsonObj = [];
$(".test-class").each(function () {
var myAttribute = $(this).data('my-attribute');
item = {}
item["MyAttribute"] = myAttribute;
jsonObj.push(item);
});
var data = { SomeOtherData: 1234, MyAttribs: jsonObj };
console.log(JSON.stringify(data));
});
</script>
</body>
</html>
In Chrome the output in the console is output as expected ...
{
"SomeOtherData": 1234,
"MyAttribs": [{
"MyAttribute": 1
}, {
"MyAttribute": 2
}, {
"MyAttribute": 3
}]
}
... but in IE the objects come out as null ...
{
"SomeOtherData": 1234,
"MyAttribs": [null, null, null]
}
I've had a look around and found some other questions that recommend checking that the page has <!DOCTYPE html> in it (which it does) and that doesn't seem to have any effect. I've also read that this should work in from IE8 onward so not sure what's happening.
Does anyone know why the objects are appearing as nulls in IE?
What is the best cross-browser solution to this?
Thanks,
Gavin
The only weird thing I see is that:
item = {}
Should be:
var item = {}; // 'var' and semicolon
Sometimes IE is quite strict..
on my case use as #palvo sayed console.dir(obj)
other alternative is JSON2 from douglascrockford

jQuery template not showing data elements

I'm trying to get the jQuery template feature working but have finally come to a dead end. From all my investigation the code listing below should work and I expect to get:
file1.txt, 123456, 2012-01-01
file2.txt, 234567, 2012-01-02
file3.txt, 345678, 2012-01-03
but instead I get
, ,
, ,
, ,
Clearly the library is loading and the code is running but for some reason it will not pick up the data elements. The code behaves the same regardless of the browser. I've tried compiling the template and not, each with the same results.
I'm sure that I'm missing something simple, but I've been pulling my hair out for about 8 hours staring at examples (and I've not that much hair left!). Thanks in advance for any assistance.
<html lang="en">
<head>
<title>jQuery Template Test</title>
<script src="http://code.jquery.com/jquery.min.js" type="text/javascript"></script>
<script src="inc/jquery.tmpl.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function() {
var exampleData = [
{ name: "file1.txt", size: "123456", date: "2012-01-01" },
{ name: "file2.txt", size: "234567", date: "2012-01-02" },
{ name: "file3.txt", size: "345678", date: "2012-01-03" }
];
var markup = "<li>${name}, ${size}, ${date}</li>";
$.template( "exampleTemplate", markup );
$.tmpl("exampleTemplate", exampleData).appendTo("#target");
});
</script>
</head>
<body>
<ul id="target"></ul>
</body>
</html>
I had the same problem with JSP: Use \$ to escape EL expression

Categories