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

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");
})})

Related

How can I interpret my JSON via Google Books API URL and display it on my HTML page using JS?

So, I am trying to pull the volume info from the JSON array from the URL provided: https://www.googleapis.com/books/v1/volumes?q=HTML5
Trying to pull author, title, images, page numbers and description.
This specific class of my HTML code I want to put the JSON data that I have mentioned above in is the 'b-card' class:
<div class="booklist">
<div class="booklist-cards">
<div class="b-card">
</div>
<div class="b-card">
</div>
<div class="b-card">
</div>
<div class="b-card">
</div>
<div class="b-card">
</div>
<div class="b-card">
</div>
<div class="b-card">
</div>
<div class="b-card">
</div>
</div>
</div>
<script src="https://www.googleapis.com/books/v1/volumes?q=HTML5"></script>
<script src="assets/js/script.js"></script>
The script.js file I have tried is below:
function handleResponse(obj) {
const book = Objects.keys(obj).map(item => obj['items']).reduce(
(acc, rec, id, array) => {
let singleBookCover = rec[id].volumeInfo.imageLinks.thumbnail;
let singleBookTitle = rec[id].volumeInfo.title;
let singleBookAuthor = rec[id].volumeInfo.authors[0];
return [...acc, {singleBookCover, singleBookTitle, singleBookAuthor}]
},
[]
).forEach( item => {
let title = document.createElement('h1');
title.textContent = `${item.singleBookTitle}`;
let author = document.createElement('strong');
author.textContent = `${item.singleBookAuthor}`;
let img = document.createElement('img');
img.src = item.singleBookCover;
img.alt = `${item.singleTitle} by ${item.singleBookAuthor}`;
let container = document.getElementsByClassName('b-card');
container.appendChild(title).appendChild(author).appendChild(img);
})
return book
}
The above code only adds the title image and author, but I cant get them to load into my HTML.
What are ways to resolve this? Am i calling the URL correctly in the HTML script tag?
Forgot to mention - would like to achieve this without using JQuery & AJAX. I have also tried inputting the callback to handleResponse in the script tag url but it doesnt work.
you can't append to the HTML because container is array so it need index of the element
container[index].appendChild(title).appendChild(author).appendChild(img);
but here simple version, and don't forget to add &callback=handleRespons to the API URL
function handleResponse(obj) {
obj.items.forEach((item, index) => {
if(index > 7) return; // limit 8 result
let div = document.createElement('div');
div.className = 'b-card';
div.innerHTML = `<h1>${item.volumeInfo.title}</h1>
<p><strong>${item.volumeInfo.authors[0]}</strong></p>
<img src="${item.volumeInfo.imageLinks.thumbnail}" alt="${item.singleTitle} by ${item.volumeInfo.authors[0]}" />`
let container = document.querySelector('.booklist-cards');
container.append(div);
})
}
<div class="booklist">
<div class="booklist-cards">
</div>
</div>
<script src="//www.googleapis.com/books/v1/volumes?q=HTML5&callback=handleResponse" async></script>

Uncaught Syntax Error: Identifier 'URL' has already been declared

This is my code even if I am changing the name from URL TO API_URL, still is the same error. By the way the code which I have written is only to learn about how API's works and learn about Twitter API.
In the backend, I am using a variable as const URL. That's I thought may be it is due to same name error in backend and the frontend. That's why I tried to change the name as I said earlier from URL TO API_URL but still it isn't working.
const URL = "http://localhost:3000/tweets";
const onEnter = (e) => {
if(e.key == "Enter"){
getTwitterData();
}
}
/**
* Retrive Twitter Data from API
*/
const getTwitterData = () => {
const query = document.getElementById("user-search-input").value;
if(!query) return;
const encodedQuery = encodeURIComponent(query);
const fullurl =`${URL}?q=${encodedQuery}&count=10`;
fetch(fullurl).then((response)=>{
return response.json();
}).then((data)=>{
buildTweets(data.statuses);
})
}
/**
* Save the next page data
*/
const saveNextPage = (metadata) => {
}
/**
* Handle when a user clicks on a trend
*/
const selectTrend = (e) => {
}
/**
* Set the visibility of next page based on if there is data on next page
*/
const nextPageButtonVisibility = (metadata) => {
}
/**
* Build Tweets HTML based on Data from API
*/
const buildTweets = (tweets, nextPage) => {
let twitterContent = "";
tweets.map((tweet)=>{
twitterContent += `
<div class="tweet-container">
<div class="tweet-user-info">
<div class="tweet-user-profile">
</div>
<div class="tweet-user-name-container">
<div class="tweet-user-fullname">
Abhishek Sagar
</div>
<div class="tweet-user-username">
#abhisheksagar_
</div>
</div>
</div>
<div class="tweet-images-container">
<div class="tweet-image">
</div>
</div>
<div class="tweet-text-container">
${tweet.full_text}
</div>
<div class="tweet-date-container">
20 hours ago
</div>
</div>`
})
document.querySelector('.tweets-list').innerHTML = twitterContent;
}
/**
* Build HTML for Tweets Images
*/
const buildImages = (mediaList) => {
}
/**
* Build HTML for Tweets Video
*/
const buildVideo = (mediaList) => {
}
Because in file html you twice write script.src

How to create multiple HTML elements from an Array?

I have a simple site that is getting a list of books from the Google Books API.
I have a separate file called scripts.js that is getting all the book information (title, author, ISBN, link to the image).
I want to create a div for each book in a gallery style page, where there is a picture of the book and on top of the book is the Title, Author, and ISBN.
I've tried creating the DIV's in Javascript but I want there to be an h3, p, and img inside of each DIV and I can't seem to wrap my head around how I could do that in Javascript.
My HTML code for the gallery:
<div id="content">
<h2>My Bookshelf</h2>
<div class="book">
<!-- The book image is the background of the div -->
<h3 class="book-title">Title</h3>
<p class="book-isbn">ISBN: 000000</p>
<p class="book-author">Authors: ABC</p>
</div>
</div>
My Javascript code that cycles through the JSON file and returns the needed information.
// Returns an array with the book title, ISBN, author, bookmark icon, description, image
apiRequest.onreadystatechange = () => {
if (apiRequest.readyState === 4) {
const response = JSON.parse(apiRequest.response);
var bookList = response.items;
// Removes old search results before display new ones
bookSection.innerHTML = "";
for (let i = 0; i < bookList.length; i++) {
console.log(i);
var title = (bookList[i]["volumeInfo"]["title"]);
try {
var isbn = (bookList[i]["volumeInfo"]["industryIdentifiers"][0]["identifier"]);
} catch (TypeError) {
var isbn = "ISBN Not Available";
}
var author = (bookList[i]["volumeInfo"]["authors"]);
var description = (bookList[i]["description"]);
try {
var image = (bookList[i]["volumeInfo"]["imageLinks"]["thumbnail"]);
} catch (TypeError) {
var image = "img/unavailable.png";
}
}
}
}
You can use template literals to make your job easier.
You can do it like this:
var bookSection = `<div id="content">
<h2>My Bookshelf</h2>
<div class="book">
<!-- The book image is the background of the div -->
<h3 class="book-title">${titleVar}</h3>
<p class="book-isbn">ISBN: ${ISBNVar}</p>
<p class="book-author">Authors: ${AuthorsVar}</p>
</div>
</div>`;
Learn more about template literals from here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals
Your code should look something like this
apiRequest.onreadystatechange = () => {
if (apiRequest.readyState === 4) {
const response = JSON.parse(apiRequest.response);
var bookList = response.items;
// Removes old search results before display new ones
bookSection.innerHTML = "";
let bookListHtmlMarkup = '';
for (let i = 0; i < bookList.length; i++) {
console.log(i);
// Declaring book object
const book = {};
const bookListHtmlMarkup = '';
book['title'] = (bookList[i]["volumeInfo"]["title"]);
try {
book['isbn'] = (bookList[i]["volumeInfo"]["industryIdentifiers"][0]["identifier"]);
} catch (TypeError) {
book['isbn'] = "ISBN Not Available";
}
book['author'] = (bookList[i]["volumeInfo"]["authors"]);
book['description'] = (bookList[i]["description"]);
try {
book['image'] = (bookList[i]["volumeInfo"]["imageLinks"]["thumbnail"]);
} catch (TypeError) {
book['image'] = "img/unavailable.png";
}
bookListHtmlMarkup += `
<div class="book">
<div class="book-image">
<img src="${book.image}" alt="Image unavailable" />
</div>
<div class="book-info">
<h3 class="book-title">${book.title}</h3>
<p class="book-isbn">ISBN: ${book.isbn}</p>
<p class="book-author">Author: ${book.author}</p>
<p class="book-description">Author: ${book.description}</p>
</div>
</div>
`;
}
// Assigning generated markup to innerHTML of bookSection
bookSection.innerHTML = bookListHtmlMarkup;
}
}

How do I give React methods to the onClick handler of an html component?

I'm trying to change the HTML received from a database to respond to custom onClick handlers. Specifically, the HTML I pull has divs called yui-navsets which contain yui_nav page selectors and yui_content page contents. I want to click an li in yui_nav, set that li's class to "selected", set the existing content to display:none, and set the new content to style="".
To do this, I have created a function updateTabs which inputs the index of the chosen yui and the new page number, set that li's class to "selected", set the existing content to display:none, and set the new content to style="". This function works: I tried running updateTabs(2, 3) in componentDidUpdate, and it worked fine, changing the content as requested. I want to assign updateTabs to each of the lis, and I attempt to do so in my componentDidMount after my axios request.
However, I keep getting the error: TypeError: this.updateTabs is not a function. Please help?
Page.js:
import React, { Component } from 'react';
import axios from 'axios';
class Page extends Component {
constructor(props) {
super(props);
this.state = {
innerHTML: "",
pageTags: [],
};
console.log(this.props.url);
}
componentDidMount() {
console.log(this.props.url);
axios
.get(
this.props.db_address + "pages?url=" + this.props.url,
{headers: {"Access-Control-Allow-Origin": "*"}}
)
.then(response => {
this.setState({
innerHTML: response.data[0].html,
pageTags: response.data[1]
});
console.log(response);
// Check for yui boxes, evade the null scenario
var yui_sets = document.getElementsByClassName('yui-navset');
if (yui_sets !== null) {
let yui_set, yui_nav, yui_content;
// Iterate through the navs of each set to find the active tabs
for (var yui_set_count = 0; yui_set_count < yui_sets.length; yui_set_count ++) {
yui_set = yui_sets[yui_set_count];
yui_nav = yui_set.getElementsByClassName('yui-nav')[0].children;
yui_content = yui_set.getElementsByClassName('yui-content')[0].children;
let tab_count;
// Give each nav and tab and appropriate ID for testing purposes
for (tab_count = 0; tab_count < yui_nav.length; tab_count ++) {
yui_nav[tab_count].onclick = function() { this.updateTabs(yui_set_count); }
yui_nav[tab_count].id = "nav-"+ yui_set_count.toString() + "-" + tab_count.toString()
yui_content[tab_count].id = "content-"+ yui_set_count.toString() + "-" + tab_count.toString()
}
}
}
})
.catch(error => {
this.setState({ innerHTML: "ERROR 404: Page not found." })
console.log(error);
});
}
updateTabs(yui_index, tab_index){
// Get all yuis
var yui_sets = document.getElementsByClassName('yui-navset');
let yui_set, yui_nav, yui_content
yui_set = yui_sets[yui_index];
yui_nav = yui_set.getElementsByClassName('yui-nav')[0].children;
yui_content = yui_set.getElementsByClassName('yui-content')[0].children;
// Identify the current active tab
var current_tab_found = false;
var old_index = -1;
while (current_tab_found == false) {
old_index += 1;
if (yui_nav[old_index].className === "selected") {
current_tab_found = true;
}
}
// Identify the new and old navs and contents
var yui_nav_old = yui_nav[old_index]
var yui_nav_new = yui_nav[tab_index]
var yui_content_old = yui_content[old_index]
var yui_content_new = yui_content[tab_index]
// Give the new and old navs and contents their appropriate attributes
yui_nav_old.className = "";
yui_nav_new.className = "selected";
yui_content_old.style = "display:none";
yui_content_new.style = "";
}
render() {
return (
<div className="Page">
<div className="Page-html col-12" dangerouslySetInnerHTML={{__html:this.state.innerHTML}} />
<div className="Page-footer">
<div className="d-flex flex-wrap btn btn-secondary justify-content-around">
{this.state.pageTags.map(function(pageTag){return(
<div className="pd-2" key={pageTag.id}>
{pageTag.name}
</div>
)})}
</div>
<div className="d-flex justify-content-center" >
<div className="p-2">Discuss</div>
<div className="p-2">Rate</div>
<div className="p-2">Edit</div>
</div>
<div className="d-flex justify-content-around App">
<div className="p-2">
Unless otherwise stated, the content
of this page is licensed under <br />
<a href="http://creativecommons.org/licenses/by-sa/3.0/"
target="_blank" rel="noopener noreferrer">
Creative Commons Attribution-ShareAlike 3.0 License
</a>
</div>
</div>
</div>
</div>
)
}
}
export default Page
Instead of function with function keyword use arrow functions and it will be solved as follows
You have
yui_nav[tab_count].onclick = function() { this.updateTabs(yui_set_count); }
But use
yui_nav[tab_count].onclick = () => { this.updateTabs(yui_set_count); }
Use this in componentDidMount method
You have to bind the updateTabs method in the constructor:
constructor(props) {
super(props);
...
this.updateTabs = this.updateTabs.bind(this);
}
You should use arrow functions in order to call this method with the correct contetxt:
yui_nav[tab_count].onclick = () => { this.updateTabs(yui_set_count); }

Access the data attribute while instantiating multiple tool-tips using tippyjs

i am creating a multiple dynamic tooltips using tippyjs library on a page that fetches content using fetch api.
how do i access the data attribute on each of the selector while the initialisation of the tooltip.
here is what i have
Code
<span class="order-tooltip" data-orderid="123456">Order ID 123456</span>
<span class="order-tooltip" data-orderid="454515">Order ID 454515</span>
<span class="order-tooltip" data-orderid="487848">Order ID 487848</span>
<span class="order-tooltip" data-orderid="154214">Order ID 154214</span>
<div id="tooltipTemplate" style="display: none;">
Loading data...
</div>
<script>
const template = document.querySelector('#tooltipTemplate')
const initialText = template.textContent
const tip = tippy('.order-tooltip', {
animation: 'shift-toward',
arrow: true,
html: '#tooltipTemplate',
onShow() {
// `this` inside callbacks refers to the popper element
const content = this.querySelector('.tippy-content')
if (tip.loading || content.innerHTML !== initialText) return
tip.loading = true
console.log($('.order-tooltip').data('orderid')) // This is not working
var orderid = $(this).data('orderid');
var url = "/fetch_position_tooltip?" + $.param({orderid: orderid})
fetch(url).then(resp => resp.json()).then (responseJSON =>{
content.innerHTML = responseJSON
tip.loading = false
}).catch(e => {
console.log(e)
content.innerHTML = 'Loading failed'
tip.loading = false
})
},
onHidden() {
const content = this.querySelector('.tippy-content')
content.innerHTML = initialText
},
// prevent tooltip from displaying over button
popperOptions: {
modifiers: {
preventOverflow: {
enabled: false
},
hide: {
enabled: false
}
}
}
})
</script>
i need to access the data attribute for each of the span element when instantiating the toolitip .
How could i do this?
Contacted the maintainer of the library
Any one looking for this can use.
this._reference

Categories