webshare API multiple instances on same page - javascript

Hopefuly someone can assist/direct me here.
I'm making use of the webshare API on my site. The site contains an array of posts that will have a share link. This is built using a foreach and all have unique urls to use. I want to add a share button to each of those images. I currently have it working on a singular instance but unable to get it to loop through all the share buttons.
Here is the current script:
const shareButton = document.querySelector('.share-button');
const url = document.querySelector('.post-link a').href;
shareButton.addEventListener('click', event => {
if (navigator.share) {
navigator.share({
title: 'Check out this ad I saw on ...',
url
}).then(() => {
console.log('Shared');
})
.catch(console.error);
}
});
I'm really struggling with how to get it to loop through all share buttons and not just be usable on the first instance.
Apologeis if this is simple.

For a start, you need to add a click listener to all buttons, not just the first. You can do this exclusively when the API is supported, else, you may want to hide the buttons. Here's the modified script (note that you need to get the URL of each post individually, see the comment):
const shareButtons = document.querySelectorAll('.share-button');
if ('share' in navigator) {
shareButtons.forEach((shareButton) => {
shareButton.addEventListener('click', () => {
// Get the URL from the dataset or query the DOM.
const url = shareButton.dataset(url);
navigator.share({
title: 'Check out this ad I saw on ...',
url
}).then(() => {
console.log('Shared');
}).catch(console.error);
});
});
} else {
shareButtons.forEach((shareButton) => {
shareButton.style.display = 'none';
});
}

Related

How would I solve this in a way to allow my database to be firstly populated by woocommerce and then allow myself to make whatever changes I wish?

I am creating an e commerce mobile app using React Native, within this I have a server, the role of the server is currently to get products from the woocommerce APi, take only the fields I need : name, id, category,price, image and then add another field called 'favourite'(for my wishlist).
Everything was worked well until the getProducts method has a method that calls the woocommerce API and then pushes that to the database. Problem is that whenever I try to update an item to 'true' rather than 'false' within the favourite field. It populates but when I refresh the page which also recalls the API, it brings the 'favourite' field back to false, which it was initially initialised as in the server.
I present the code in question:
app.get("/getProductsForUser", async (req, res) => {
const productDetails = {};
const numberOfProducts = 25;
api
.get("products", {
per_page: numberOfProducts, // 20 products per page
})
.then((response) => {
// Successful request
var key = "Products";
productDetails[key] = [];
var data;
for (let index = 0; index < numberOfProducts; index++) {
productDetails[key].push({
id: response.data[index].id,
name: response.data[index].name,
image: response.data[index].images[0].src,
price: response.data[index].price,
favourite: false,
category: response.data[index].categories[0].name,
});
}
db.collection("users")
.doc(req.query.userID)
.collection("products")
.doc("0")
.set({ productDetails });
res.send(productDetails);
})
.catch((error) => {
// Invalid request, for 4xx and 5xx statuses
console.log("Response Status:", error);
})
.finally(() => {
// Always executed.
});
});
If there is a way I can only call the above function once in the whole project (which is in nodejs by the way) and then after that only call from the database, that will help?
Just get your stored product in the DB before you push the product to the list: something like :
for (let index = 0; index < numberOfProducts; index++) {
const storedProduct = db.collection("products").getByID(response.data[index].id);
productDetails[key].push({
id: response.data[index].id,
name: response.data[index].name,
image: response.data[index].images[0].src,
price: response.data[index].price,
favourite: storedProduct.favourite ,
category: response.data[index].categories[0].name,
});
}
so instead of setting it always to false set it to the stored value.
You could also implement it in a different way. where you don't have to get the products every time for the woocommerce API. to provide you with such a solution I will need more context to your application. for example, do you have a way to run timely triggered scripts? or is it possible to call the woocommerce API somewhere else and store the results in the DB so you don't need to call it every time the you have a call to /getProductsForUser

How execute javascript after a component change in angular?

My code works fine when I write in browser localhost:4200/pay;id=1. This show Pay component with credit card fields generated by a external javascript (This javascript script is loaded from this component). But if i come from another component to this, Pay component doesn't show the credit card fields but load external script. How can I fix this?
My code
first.component.ts
let datos = {
id:'6'
}
this.router.navigate(['pay',datos]);
pay.component.ts
ngOnInit(): void {
this.loadScripts();
}
loadScripts() {
this.dynamicScriptLoader.load('2payjs').then(data => {
// Script Loaded Successfully
console.log('All elements loaded successfully')
this.loadElement();
}).catch(error => console.log(error));
}
loadElement(){
let that = this;
let id = this.router.snapshot.paramMap.get('id');
window.addEventListener('load', function() {
// Initialize the JS Payments SDK client.
let jsPaymentClient = new TwoPayClient('AVLRNG');
// Create the component that will hold the card fields.
let component = jsPaymentClient.components.create('card');
component.mount('#card-element');
// Handle form submission.
document.getElementById('payment-form').addEventListener('submit', (event) => {
event.preventDefault();
/// Extract the Name field value
const billingDetails = {
name: document.querySelector('#name').value
};
// Call the generate method using the component as the first parameter
// and the billing details as the second one
jsPaymentClient.tokens.generate(component, billingDetails).then((response) => {
//console.log(response.token);
let data = {
token:response.token
}
}).catch((error) => {
console.error(error);
});
});
});
}
const navigationExtras: NavigationExtras = {
queryParams: {
id: 1,
},
queryParamsHandling: 'merge'
};
this.router.navigate(['pay'], navigationExtras);
you need navigationExtras in order to create params in your router link and able to fetch by another component
Already solved. I just delete window load event listener.

How to send ID with axios.delete() request

I'm making Todo List project (Pure js) and I'm trying to bind backend (node.js/express.js) with frontend. I'm stuck on the axios.delete(). All i want it to do is:When button "delete" is clicked, delete that item from the page and from the database, but I don't know how to pass the id of that item.
I am new to JavaScript.
const deleteData = () => {
axios.delete('http://localhost:3000/delete/:id', {
})
}
const deleteData = (id) => {
axios.delete('http://localhost:3000/delete/${id}', {
})
}
Did you tried this?
look for Template strings:
https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Template_literals

(Reddit API) How to get a list of subreddits user is subscribed to, using snoowrap?

So I'm using snoowrap to write a Chrome extension that gets a list of subreddits the user is subscribed, and subscribes to them on a different account.
I'm trying to get the list of subreddits currently but can't figure out how to do it. I've tried simply getting the JSON from https://www.reddit.com/subreddits/mine.json, which returns an empty object (persumably because no auth) and I have no idea how to do it via snoowrap. I looked through the documentation and can't find an option for it.
My code:
document.addEventListener('DOMContentLoaded', function() {
var login = document.getElementById('login');
login.addEventListener('click', function() {
const r = new snoowrap({
userAgent: '???',
clientId: '<id>',
clientSecret: '<clientsecret>',
username: '<username-here>',
password: '<password-here>'
});
r.getHot().map(post => post.title).then(console.log);
});
var getSubs = document.getElementById('get-subs');
getSubs.addEventListener('click', function() {
fetch('https://www.reddit.com/subreddits/mine.json')
.then(function(data) {
console.log(JSON.stringify(data));
})
.catch(function(error) {
console.log('error');
});
});
});
Not sure how else to try. Anyone have suggestions? I'd like to use snoowrap for this ideally.
When using snoowrap as API wrapper, after connecting to the api with:
const r = new snoowrap({...});
They provide a function for getting your own subscribed subreddits:
r.getSubscriptions();
This will return a Listing Object, which you can use like an Array.

Use sequelize query results inside a jquery event handler

There is an electron framework that gives you a stripped down browser to build your user interface for the desktop application. In my case, I am using jQuery for DOM navigation, Sequelize to talk to my sqlite database and a couple other libraries.
Let's say I have a text field where the user can type a movie name. My database stores a couple hundred movie names. So I would like to offer the user autocomplete suggestions.
Typically, I would use something like this to register a jQuery handler (this will echo field input back to console):
$('#movie-search-field').on('input', (event) => {
console.log(event.target.val())
})
With sequelize, you would typically have a model (say, Movie) and query it like so: Movie.findAll(). Here comes the problem:
If I register my handler like so:
Movie.findAll().then((movies) => {
$('#movie-search-field').on('input', (event) => {
/*Use movies here to build and show a suggestions list*/
})
})
then it never gets triggered. I have verified that the .then clause is entered by printing movies to console from within it.
On the other hand, if I try to query the database from inside the handler:
$('#movie-search-field').on('input', (event) => {
Movies.findAll().then((movies) => {
/*Use movies to build and show a suggestions list*/
})
})
then the handler exits before the promise is resolved and no suggestions are shown.
How could I use the database query results in my event handler?
You could just make a simple callback
$('#movie-search-field').on('input', (event) => {
getResults(function(movies) {
/* Display your movies */
})
})
function getResults(callback) {
Movies.findAll().then((movies) => {
/*Use movies to build and show a suggestions list*/
callback(movies)
})
}
So when a user types in the input box it will request the suggestions and then when it returns them it will call the function (callback) and then you can display them
Turns out I made some unrelated mistakes in my event handler code and so the approach I described above works just fine:
Movie.findAll().then((movies) => {
$('#movie-search-field').on('input', (event) => {
/*Use movies here to build and show a suggestions list*/
})
})
Also, if you are doing several database queries and would like your handler to have access to all of those, you can do:
let movies = Movie.findAll()
let tickets = Ticket.findAll()
Promise.all([movies, tickets]).then(values => {
let [movies, tickets] = values
/* register your handlers here and pass the data to them */
$("#some-selector").on('input', {movies: movies, tickets: tickets}, (event) => {
let movies = event.data.movies
let tickets = event.data.tickets
/* some event handling code that uses both movies and tickets */
})
})

Categories

Resources