Opera Mini and XMLHTTpRequest() - javascript

This relates to my previous question.
I have created the following script, which takes information from an API and displays it on a webpage using template literals. Everything works fine, expect in Opera Mini, where the data from the API does not load.
<script language="JavaScript">
window.onload = function(){
//// UI templates
var app = document.getElementById('root')
var container = document.createElement('div')
container.setAttribute('class', 'container')
app.appendChild(container)
cardHeight = window.innerHeight
const API = 'https://api.the-odds-api.com/v3/odds/?sport=soccer_epl&region=uk&apiKey=KEY'
const xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
let data = JSON.parse(xhr.responseText)
console.log(data, 'data')
data.data.forEach((match, index) => {
console.log(match, 'match')
const card = document.createElement('div')
card.setAttribute('class', 'card')
const odds = match.sites[0].odds
// styles
const cssClasses = {
team: 'flex flex-row',
radio: 'mla',
title: 'f4'
}
const markup = `
<div class='mb3 flex flex-column bg-near-white' style="height: ${cardHeight}px">
<div class="${cssClasses.team}">
<h2 class="${cssClasses.title}">${match.teams[0]}</h2>
<span class="${cssClasses.radio}">${odds.h2h[0]}<input type="radio" name="${index}" value="1"></span>
</div>
<div class="${cssClasses.team}">
<h2 class="${cssClasses.title}">Draw</h2>
<span class="${cssClasses.radio}">${odds.h2h[1]}<input type="radio" name="${index}" value="1"></span>
</div>
<div class="${cssClasses.team}">
<h2 class="${cssClasses.title}">${match.teams[1]}</h2>
<span class="${cssClasses.radio}">${odds.h2h[2]}<input type="radio" name="${index}" value="1"></span>
</div>
</div>
`;
card.innerHTML = markup
console.log(card, 'card')
container.appendChild(card)
})
}
if (xhr.status == 404) {
console.log("not working")
}
}
}
xhr.open('get', API, true);
xhr.send();
}
</script>
Is there something I am doing wrong?
I am using the odds API

Related

How can I get action events to work with template strings

Problem
Rendered HTML template literal action events won't work
Stack MEVN with handlebars
code
renderData.js
const template = function (data) {
return `<div class="vvn_siteContent sc_flex">
<span class="sc_flex">
<img src="https://images.wallpaperscraft.com/image/single/keyboard_backlight_light_159518_1280x720.jpg" alt="" class="sc_img">
<div class="sc_flex sc_column">
<label class="sc_label">${data.category} :: ${data.titles.main}</label>
<div class="sc_desc" style="word-wrap: break-word">
${data.desc.main}
</div>
<div class="vvn_editTypes">
<button class="sc_button sc_resetBTN">Delete</button>
<button class="sc_button sc_scheduleBTN" >Hide</button>
<button class="sc_button sc_sendBTN" dataset-data="${data._id}" onclick="myData()" >Edit!</button>
</div>
</div>
</span>
</div>`
}
export const renderData = function (key) {
const keyToLowerCase = key.toLowerCase();
const getKeyData = handleJSON(keyToLowerCase);
getContainer.innerHTML = " ";
const parser = new DOMParser();
for (let i = 0; i < getKeyData[0][0].pageContent.length; i++) {
const { ...data } = getKeyData[0][0].pageContent[i];
const html = template(data);
const parsedDoc = parser.parseFromString(html, "text/html");
getContainer.append(...parsedDoc.body.children);
}
}
oneCRUD.js //this is the file that is loaded via
<script type="module" src="../js/OneCRUD.js" type="text/javascript" data="{{data2}}"></script>
this script tag is at the bottom of the index.html
const allBtns = document.querySelectorAll('.vvn_editTypes').forEach(el => el.addEventListener('click', (e) => {
console.log(e.target)
console.log(e)
if(e.target.textContent === 'Delete') console.log('Deleting')
if(e.target.textContent === 'Hide') console.log('Hiding')
if(e.target.textContent === 'Edit!') console.log('Editing')
}))
function myData () {
console.log('this wont get called even if i gave the button onclick="myData()")
}
If I try to call a function in onclick I will get error function name undefined
My problem is pretty straight forward. I am trying to attach events to the buttons in renderData.js from file oneCRUD.js and its not working.
Appreciate the help
I found a solution
code
const allBtns = document.querySelectorAll('.vvn_siteContent').forEach(el => el.addEventListener('click', (e) => {
console.log(e.target)
console.log(e)
if(e.target.textContent === 'Delete') console.log('Deleting')
if(e.target.textContent === 'Hide') console.log('Hiding')
if(e.target.textContent === 'Edit!') console.log('Editing')
}))
notice how the element I'm selecting is inside the template literal
I need to select the parent of that element.
so now my code looks like this:
const allBtns = document.querySelectorAll('.vvn_siteContentList').forEach(el => el.addEventListener('click', (e) => {
console.log(e.target)
console.log(e)
if(e.target.textContent === 'Delete') console.log('Deleting')
if(e.target.textContent === 'Hide') console.log('Hiding')
if(e.target.textContent === 'Edit!') console.log('Editing')
}))
now the allBtns function works.
why does this work?
thats a good question

Stripe card-element not showing on injected script of chrome extension

I would like to inject a Modal popup from content.js in chrome extension that allows the user to pay from the Modal.
I even tried doing async with strip mount function, waiting for document to load & this solution & I get:
Error: ReferenceError: Stripe is not defined
How to reproduce?
Use this code in console. What shall I do?
$(document).ready(function() {
const subscriptionPopup = `
<div class="container">
<div id="myPopup" class="popup hide overlay" style="height:500px !important;">
<div class="popup-body" id="popup-body">
<div id="card-element" style="background:#FF0000 ">
<!-- the card element will be mounted here -->
<p>HEREE</p>
</div>
</div>
</div>
`
function injectScript(src) {
return new Promise((resolve, reject) => {
const script = document.createElement('script');
script.src = src;
script.addEventListener('load', resolve);
script.addEventListener('error', e => reject(e.error));
document.head.appendChild(script);
});
}
injectScript('https://js.stripe.com/v3/').then(() => {
var stripe = Stripe('pk_test_A7jK4iCYHL045qgjjfzAfPxu');
var elements = stripe.elements();
var elements = stripe.elements();
var style = {
base: {
color: "#32325d",
}
};
var card = elements.create("card", { style: style });
card.mount("#card-element");
})})

Already known weather for city should not repeat again

I'm trying my first weather api APP. Here I'm trying to achive that if the city weather is already displayed , It should give the message "You already know the weather" . and should not repeat the weather
Here is my code. Anyone Please look at my code ...
What is the mistake I have been made.
<div class="main">
<div class="container">
<div class="search_por">
<h2>Weather </h2>
<div class="validate_msg color_white"></div>
<form>
<label for=""></label>
<input type="search" class="input_text" value="">
<button type="submit" id="sub_button" class="srh_button">Search</button>
</form>
<!-- <canvas id="icon1" width="150" height="75"></canvas> -->
<div class="dat_weather">
<ul id="list_it">
</ul>
</div>
</div>
</div>
</div>
var get_text=document.querySelector("form");
get_text.addEventListener("submit",e=>{
e.preventDefault();
var input_val=document.querySelector('input').value;
const apiKey="bc4c7e7826d2178054ee88fe00737da0";
const url=`https://api.openweathermap.org/data/2.5/weather?q=${input_val}&appid=${apiKey}&units=metric`;
fetch(url,{method:'GET'})
.then(response=>response.json())
.then(data=>{console.log(data)
const{main,sys,weather,wind}=data;
//icons-end
var error_ms=document.getElementsByClassName("validate_msg")[0];
var iconcode = weather[0].icon;
console.log(iconcode);
var li=document.createElement("Li");
var weatherinfo=`<div class="nameci font_40" data-name="${data.name},${sys.country}"><span>${data.name}</span><sup>${sys.country}</sup></div>
<div class="temp_ic">
<img class="weat_icon" src="http://openweathermap.org/img/w/${iconcode}.png">
<div class="deg">${Math.floor( main.temp )}<sup>o</sup></div>
</div>
<div class="clear">
<div>${weather[0].description}</div>
</div>
`;
li.innerHTML=weatherinfo;
var ulid=document.getElementById("list_it");
ulid.appendChild(li);
var city_name=data.name;
console.log(skycons);
var listitems=document.querySelectorAll('#list_it');
const listArray=Array.from(listitems);
if(listArray.length>0)
{
var filtered_array=listArray.filter(el=>{
let content="";
if(input_val.includes(','))
{
if(input_val.split(',')[1].length>2)
{
alert("hving 2 commos");
inputval=input_val.split(',')[0];
content=el.querySelector(".nameci span").textContent.toLowerCase();
//content=el.querySelector(".nameci").innerHTML.toLowerCase();
//content=inputval.toLowerCase();
}
else
{
content=el.querySelector(".nameci").dataset.name.toLowerCase();
}
alert(filtered_array);
}
else
{
content=el.querySelector(".nameci span").textContent.toLowerCase();
}
console.log(inputval.toLowerCase());
return inputval.toLowerCase();
});
if(filtered_array.length>0)
{
console.log(filtered_array.length);
error_ms.innerHTML="You Already know the weather of this country....";
get_text.reset();
return;
}
}
})
.catch((error)=>{
error_ms.innerHTML="Please Enter a valid city Name";
});
var error_ms=document.getElementsByClassName("validate_msg")[0];
error_ms.innerHTML="";
//var get_text=document.querySelector("form");
get_text.reset();
});
My full code is here:
https://codepen.io/pavisaran/pen/wvJaqBg
Let's try keeping track of a list of displayed locations outside of the callback:
var get_text = document.querySelector("form");
// Keep Track Of Displayed Cities Here Instead
let displayed = [];
get_text.addEventListener("submit", e => {
e.preventDefault();
var input_val = document.querySelector('input').value;
const apiKey = "bc4c7e7826d2178054ee88fe00737da0";
const url = `https://api.openweathermap.org/data/2.5/weather?q=${input_val}&appid=${apiKey}&units=metric`;
fetch(url, {method: 'GET'})
.then(response => response.json())
.then(data => {
var error_ms = document.getElementsByClassName("validate_msg")[0];
const {main, sys, weather, wind, name} = data;
if (displayed.length > 0) {
// Filter Displayed Based on Current vs name from data (response)
const filtered_array = displayed.filter(el => el === name);
if (filtered_array.length > 0) {
error_ms.innerHTML = "You Already know the weather of this country....";
get_text.reset();
return Promise.resolve();
}
}
// Add City To Array of Displayed Cities
displayed.push(name);
// Do Rest of Code to Add New City
var iconcode = weather[0].icon;
var li = document.createElement("Li");
var weatherinfo = `<div class="nameci font_40" data-name="${data.name},${sys.country}"><span>${data.name}</span><sup>${sys.country}</sup></div>
<div class="temp_ic">
<img class="weat_icon" src="http://openweathermap.org/img/w/${iconcode}.png">
<div class="deg">${Math.floor(main.temp)}<sup>o</sup></div>
</div>
<div class="clear">
<div>${weather[0].description}</div>
</div>
`;
li.innerHTML = weatherinfo;
var ulid = document.getElementById("list_it");
ulid.appendChild(li);
})
.catch((error) => {
error_ms.innerHTML = "Please Enter a valid city Name";
});
var error_ms = document.getElementsByClassName("validate_msg")[0];
error_ms.innerHTML = "";
get_text.reset();
});
You have to just check for the value which is coming from api whether it's present on your list or not. you can try this.
li.innerHTML=weatherinfo;
var ulid=document.getElementById("list_it");
var isPresent = false;
var items = ulid.getElementsByTagName("li");
for (var i = 0; i < items.length; i++){
if(items[i].innerHTML == li.innerHTML){
alert("you already know the weather")
isPresent = true;
}
}
if(!isPresent){
ulid.appendChild(li);
}

Why am I not getting a status code of 200?

I am using the github api to display the user info and repos on a webpage.
<body>
<section id='input'>
<h1>Github Repository Obtainer</h1>
<input type="text", id="input-text", placeholder="Enter a Github username">
<button id="submit-button">Search</button>
</section>
<hr>
<section id="main">
<ul id="tag">
<li class="tag-item">User Info</li>
<li class="tag-item">User Repository</li>
</ul>
<hr>
<section id="user">
</section>
<section id="repo">
<ul id="repository-list">
</ul></section>
</section>
<script src="index.js"></script>
</body>
</html>
button = document.getElementById("submit-button");
button.addEventListener("click", () => {
const user = document.getElementById("input-text").value;
const xmr = new XMLHttpRequest();
xmr.open("GET", `https://api.github.com/users/${user}/repos`, true);
xmr.onload = () => {
let list = document.getElementById("repository-list")
if(this.status === 200){
console.log(this.status)
const data = JSON.parse(this.responseText);
var output = '';
data.forEach((item, index) => {
let tempChild = document.createElement("li")
tempChild.setAttribute("id", "list-item")
output += `<ul>
<li><span>Name:</span> ${item.name}</li>
<li><span>Description:</span> ${item.description}</li>
<li><span>URL:</span> ${item.html_url}</li>
</ul>`
tempChild.innerHTML = output
list.appendChild(tempChild)
})
} else {
list.innerHTML = "<h1>User cannot be found</h1>"
}
}
xmr.send();
const xmr2 = new XMLHttpRequest();
xmr2.open("GET", `https://api.github.com/users/${user}`, true);
xmr2.onload =() => {
if(this.status === 200){
const data2 = JSON.parse(this.responseText);
var output = '';
output += `<h1>${data2.login}</h1>
<img src="${data2.avatar_url}">
<ul id="user-info-list">
<li><span>Bio: </span>${data2.bio}</li>
<li><span>Public Repositories: </span>${data2.public_repos}</li>
<li><span>Public Gists: </span>${data2.public_gists}</li>
<li><span>Followers: </span>${data2.followers}</li>
<li><span>Following: </span>${data2.following}</li>
<li><span>Location: </span>${data2.location}</li>
<li><span>Created on: </span>${data2.created_at.slice(0, 10)}</li>
<li><span>URL: </span>${data2.html_url}</li>
<ul>`
} else{
var output = "<h1>User does not exist</h1>"
}
document.getElementById("user").innerHTML = output
}
xmr2.send()
tabChecker();
})
tabChecker() is another function in the js file, which I have not included here. It is not causing the problem.
The output is always user not found even though the user exists on github.
Please provide answers to what the problem might be.
Also when I console.log(this.status) the output in console is blank.
The links for the api works fine when I put the link in the browser
You should use xmr2.status instead of this.status OR don't use arrow function: xmr2.onload = function() {...}. Arrow functions don't have its own this.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions

Website dynamic content

Is there any javascript library that I can use to serve HTML content? I would like to create a DIV that the content can be dynamically changed.
<div id="header">
<h2>Header here</h2>
</div>
<div id="dynamic-content">
<p>-- Dynamic content here --</p>
</div>
<div id="footer">
<h3>Footer</h3>
</div>
I'm planning to use jQuery for this, just retrieving the HTML markup from the server and then use jQuery's html() function to replace the content of #dynamic-content. I'm just curious if this is practical if the retrived HTML markup is "large", lets say a whole article.
Is there a simple JavaScript templating framework for this? Or can I even use templating JS frameworks for this?
--Helper--
var uiHelper = function () {
var htmls = {};
var getHTML = function (options) {
/// <summary>Returns HTML in a string format</summary>
/// <param name="options" type="object">options{url:The url to the file with the HTML,successCallback:function,errorCallback:function,isAsync:true||false,cache:true|false}</param>
function xhrSuccess() {
if (this.cache) { htmls[this.url] = this.responseText; };
if (this.successCallback) {
this.successCallback.apply(this.responseText, this.arguments);
} else {
return htmls[this.url];
};
};
function xhrError() {
if (this.errorCallback) {
this.errorCallback.apply(this.statusText);
} else {
return this.statusText;
};
};
if (!htmls[options.url]) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", options.url, options.isAsync);
xmlhttp.cache = options.cache || false;
xmlhttp.url = options.url;
xmlhttp.onload = xhrSuccess;
xmlhttp.onerror = xhrError;
xmlhttp.successCallback = options.successCallback || undefined;
xmlhttp.errorCallback = options.errorCallback || undefined;
xmlhttp.send();
} else {
if (options.successCallback) {
options.successCallback.apply(htmls[options.url], this.arguments);
} else {
return htmls[options.url];
};
};
};
return {
getHTML: getHTML
};
}();
--Usage---
uiHelper.getHTML({
url: url, isAsync: true, cache: false, successCallback: function () {
document.getElementById('dynamicContent').innerHTML = this;
}
});
--Your HTML---
<div id="header">
<h2>Header here</h2>
</div>
<div id="dynamic-content">
<p id='dynamicContent'>-- Dynamic content here --</p>
</div>
<div id="footer">
<h3>Footer</h3>
</div>
Well,I recommend you this jquery plugin: jquery.tmpl
github: https://github.com/BorisMoore/jquery-tmpl
this is the introduction:
ppt: http://skilldrick.co.uk/tmpl/
article: http://footyntech.wordpress.com/2013/08/20/simple-javascript-templating-with-jquery-tmpl/
: )

Categories