I'm making a food sharing site using firebase I'm trying to add a delete post option so when a food item is taken the user can delete the post so they aren't contacted about something they've already given away. I have managed to get the firebase remove function working but it just deletes all posts not just one. I'm using the push option when sending the data to my database as I need users to be able to make multiple posts but I don't know what the name of the post ids are to select them.
This is the code that sends the donations to the database
function submitDonation() {
var user = firebase.auth().currentUser;
if(user) {
var userid = user.uid;
var email = user.email;
var firebaseRef = firebase.database().ref();
firebaseRef.child("Donations").push({
user: userid,
email: email,
food: document.getElementById("foodType").value,
animal: document.getElementById("animalType").value,
expire: document.getElementById("expirationDate").value,
travel: document.getElementById("travelDistance").value,
location: document.getElementById("what3wordsLocation").value,
contact: document.getElementById("contactPreference").value,
time: document.getElementById("timePreference").value
});
}
}
and this is the code retrieving and drawing the data on the page. I'm using jquery to display my posts so sorry it looks a bit messy but I've basically got a button that calls a function and I need the button's id to match the id of the post but I don't know how to call that. Any help would be much appreciated. I'm still relatively new to firebase so still working on the basics aha.
var rootRef = firebase.database().ref().child("Donations");
rootRef.on("child_added", snap => {
var food = snap.child("food").val();
var animal = snap.child("animal").val();
var expire = snap.child("expire").val();
var travel = snap.child("travel").val();
var location = snap.child("location").val();
var contact = snap.child("contact").val();
var time = snap.child("time").val();
$("#listingDonations").append(
"<div id='donationBox' class='three columns'><div id='donationItem'><button onclick='deletePost()'>Delete</button><p><b>Type of Food:</b> " + food + "</p><p><b>Type of Animal:</b> " + animal + "</p><p><b>Expiration Date:</b> " + expire + "</p><p><b>Travel Distance:</b> " + travel + "</p><p><b>Contact Details:</b> " + contact + "</p><p><b>Preferred Contact Time:</b> " + time + "</p><a href='https://www.what3words.com/"+ location +"'>Location</a></div></div>"
);
})
function deletePost() {
}
Ive deleted the code I'd written in the deletePost function as it didn't work and is probably wrong anyway.
I'm trying to build a simple tool that will return a Github profile when you search someone's username. Everything seems to be working, except when I search for a different user, the list of followers from the previous user search don't clear.
For example, a user who has seven followers will suddenly have dozens of follower avatars displaying.
Can anyone tell me how to display the correct number of followers unique to each user when fetching different Github profiles?
var response = null;
var followers = null;
document.getElementsByTagName('button')[0].addEventListener('click', function(r) {
getUser(document.getElementsByTagName('input')[0].value);
});
function getUser(name) {
fetch('https://api.github.com/users/' + name)
.then(function(r) {
console.log(r.status);
return r.json();
})
.then(function(j) {
response = j;
assignValues();
getFollowers(j.followers_url);
});
}
function assignValues() {
document.getElementById('loader').style = 'display: none';
document.getElementById('avatar').src = response.avatar_url;
document.getElementById('name').innerText = response.name;
document.getElementById('username').innerText = response.login;
document.getElementById('location').innerText = response.location;
document.getElementById('bio').innerText = response.bio;
document.getElementById('count').innerText = 'Followers: ' + response.followers;
}
function getFollowers(url) {
fetch(url)
.then(function(r) {
return r.json();
})
.then(function(f) {
followers = f;
listFollowers();
});
}
function listFollowers() {
followers.forEach(function(f) {
var li = document.createElement('li');
li.innerHTML = ''+ '<img src="' + f.avatar_url + '" alt="' + f.login + '"/>'+ '';
document.getElementById('list').appendChild(li);
});
}
You need to clear that #list element in listFollowers function before starting appending new followers to it. For example:
var list = document.getElementById('list');
list.innerHTML = '';
followers.forEach(function(f) {
var li = document.createElement('li');
li.innerHTML = ''+ '<img src="' + f.avatar_url + '" alt="' + f.login + '"/>'+ '';
list.appendChild(li);
});
Three sidenotes here:
why do you use global variables response and followers in your rendering functions when you can pass those as arguments?
as you rerender a 'user profile' first, then wait for avatars' fetch, it's still possible for a user to see the followers of user X when looking for user Y. It's better to clear that section (and show some visual cue for loading data) immediately after the user is switched.
as order of fetch responses is not guaranteed, there's a potential race condition here: if user clicks on that button twice (with different inputs), the earlier input might get back later - and overwrite the former. You need to guard against this, either by storing the latest input value and checking the response, or by some other means.
You can test those by artificially throttling the network speed. And believe me, in real world most of your user will have all sorts of problems with that.
Attempting to create a script that will pull information from an API requested XML document and put it into a 2D array.
Upon making the Get request
https://api.example.com/v1.svc/users?apikey=MY-KEY&source=MY-APP&limit=1000
An XML is produced for each user looking like
<User>
<Id>Rdh9Rsi3k4U1</Id>
<UserName>firstlast#email.com</UserName>
<FirstName>First</FirstName>
<LastName>Last</LastName>
<Active>true</Active>
<Email>firstlast#email.com</Email>
<AccessLevel>Learner</AccessLevel>
</User>
Each user has a similar looking output stacked on top of each other. How could this be scrubbed into an array? Example, the first array would have 7 "columns" with all shown information with each user having a row.
b
So I figured it out for anyone looking for an answer to this type of question in the future. Basically, I found out that the API I was trying to reach (not actually "citrowske.com" as shown in the example) did not allow for CORS or jsonp which left me with the only option of using a Proxy.
Shown is an example of code similar to what I ended up using (below), along with the test XML file shown here
A basic explanation of how this works, it uses the proxy to get the XML file and stores it as "xml" found as "function(xml)". Then the XML doc is searched and each section that starts with "User" gets the "FirstName" and "LastName" data pulled from it and appended to dropdown in the HTML section named "yourdropdownbox".
$.ajaxPrefilter( function (options) {
if (options.crossDomain && jQuery.support.cors) {
var http = (window.location.protocol === 'http:' ? 'http:' : 'https:');
options.url = http + '//cors-anywhere.herokuapp.com/' + options.url;
//options.url = "http://cors.corsproxy.io/url=" + options.url;
}
});
$.get(
'http://citrowske.com/xml.xml',
function (xml) {
//console.log("> ", xml);
//$("#viewer").html(xml);
////////////////////////////////////
var select = $('#yourdropdownbox');
select.append('<option value="">Select a User</option>');
$(xml).find('User').each(function(){
var FirstNames = $(this).find('FirstName').text();
var LastNames = $(this).find('LastName').text();
select.append("<option value='"+ FirstNames +"'>"+FirstNames+" "+LastNames+"</option>");
});
}
////////////////////////////////////
);
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<select id="yourdropdownbox">
</select>
As a note, Proxy's are not known for being extremely secure, so watch out what you use this for.
Also, if I wanted to turn the data into an array instead of appending it each time I could have added
var firstnamesarray = ["0"];
var lastnamesarry = ["0"];
var i = 0;
Above the top row of forward-slashes and then replaced:
var FirstNames = $(this).find('FirstName').text();
var LastNames = $(this).find('LastName').text();
with
firstnamesarry[i] = $(this).find('FirstName').text();
lastnamesarry[i] = $(this).find('LastName').text();
i = i+1;
and replaced the "select.append" First & Last Names with
firstnamearry[i] & lastnamearry[i]
To view a working example, check out the jsfiddle here
this is my first time here as a poster, please be gentle! I have zero knowledge of JS (yet, working on it) but am required to do some JS anyway. Here's my problem. I got some code (not mine) allowing a user to select multiple choices. I found the function that gathers these choices and store them
function getProductAttribute()
{
// get product attribute id
product_attribute_id = $('#idCombination').val();
product_id = $('#product_page_product_id').val();
// get every attributes values
request = '';
//create a temporary 'tab_attributes' array containing the choices of the customer
var tab_attributes = [];
$('#attributes select, #attributes input[type=hidden], #attributes input[type=radio]:checked').each(function(){
tab_attributes.push($(this).val());
});
// build new request
for (var i in attributesCombinations)
for (var a in tab_attributes)
if (attributesCombinations[i]['id_attribute'] === tab_attributes[a])
request += '/'+attributesCombinations[i]['group'] + '-' + attributesCombinations[i]['attribute'];
$('#[attsummary]').html($('#[attsummary]').html() + attributesCombinations[i]['group']+': '+attributesCombinations[i]['attribute']+'<br/>')// DISPLAY ATTRIBUTES SUMMARY
request = request.replace(request.substring(0, 1), '#/');
url = window.location + '';
// redirection
if (url.indexOf('#') != -1)
url = url.substring(0, url.indexOf('#'));
// set ipa to the customization form
$('#customizationForm').attr('action', $('#customizationForm').attr('action') + request);
window.location = url + request;
}
I need to make a simple display summary of these choices. After quite a bit of searching and findling, I came with the line with the DISPLAY SUMMARY comment, this one:
$('#[attsummary]').html($('#[attsummary]').html() + attributesCombinations[i]['group']+': '+attributesCombinations[i]['attribute']+'<br/>')
In the page where I want those options, I added an empty div with the same ID (attsummary):
<div id="attsummary"></div>
Obviously, it is not working. I know I don't know JS, but naively I really thought this would do the trick. May you share with me some pointers as to where I went wrong?
Thank you very much.
Correct form of the line it isn't working for you:
$('#attsummary').html($('#attsummary').html() + attributesCombinations[i]['group']+': '+attributesCombinations[i]['attribute']+'<br/>')
I'm still pretty new to Javascript, but I was wondering what would be the best way to fire the Facebook conversion pixel (below) without actually loading a "confirmation"/"Thank You" page?
<script type="text/javascript">
var fb_param = {};
fb_param.pixel_id = 'XXXXXXXXXXX';
fb_param.value = '0.00';
fb_param.currency = 'USD';
(function(){
var fpw = document.createElement('script');
fpw.async = true;
fpw.src = '//connect.facebook.net/en_US/fp.js';
var ref = document.getElementsByTagName('script')[0];
ref.parentNode.insertBefore(fpw, ref);
})();
</script>
<noscript><img height="1" width="1" alt="" style="display:none"
src="https://www.facebook.com/offsite_event.php?id=XXXXXXXXXX&value=0¤cy=USD" /></noscript>
Facebook says that we should plug this into our "Thank You pages" that visitors see after they convert (fill out a form, make a purchase, etc). However, some of our forms are popups or forms on sidebars next to content that we don't want readers to be directed away from by a confirmation page.
With Google Analytics, I can create an "invisible" pageview by firing _gaq.push(['_trackPageview']); code that can tell GA that it should count that invisible pageview as a goal completion.
Is there something similar to that that's general enough to tell my site to fire the FB pixel?
EDIT: I've updated my code as what I had mentioned previously did not work. Thanks to #Flambino to pointing out.
This is my revised answer using a pixel rather than a script to pass the conversion pixel. I reference the How to track a Google Adwords conversion onclick? SO post:
<head>
<script type="text/javascript">
function facebookConversionPixel(fb_pixel, fb_value){
var image = new Image(1,1);
image.src = "//www.facebook.com/offsite_event.php?id=" + fb_pixel + "&value=" + fb_value + "¤cy=USD";
}
</script>
</head>
<body>
FBCONV
</body>
From the FB docs "How to track in-page events":
After the base code snippet is installed, you can track in-page actions, such as clicks on a button, by making a _fbq.push('track') call for the conversion pixel through registering different event handlers on an HTML DOM element. For example:
function trackConversionEvent(val, cny) {
var cd = {};
cd.value = val;
cd.currency = cny;
_fbq.push(['track', '<pixel_id>', cd]);
}
<button onClick="trackConversionEvent('10.00','USD');" />
Just move the entire original code into the event of your choice. Then just change 1 part of the code. The thing you will have to do is make the fb_param global instead of local.
See below at the comment
$('.button').click(function() {
window.fb_param = {}; // must be global by adding `window.`
fb_param.pixel_id = '123456789';
fb_param.value = '0.00';
fb_param.currency = 'USD';
(function(){
var fpw = document.createElement('script'); fpw.async = true; fpw.src = '//connect.facebook.net/en_US/fp.js';
var ref = document.getElementsByTagName('script')[0];
ref.parentNode.insertBefore(fpw, ref);
})();
});
I was having similar kind of issue and I would like to run multiple adds to track pixels codes and some reason I was not able to track. What I did is that, in the current page I have added pixel code in footer and javascript function
to call when my ajax button get submitted.
First refer to Facebook documentation page
https://developers.facebook.com/docs/ads-for-websites/conversion-pixel-code-migration#multi-conv-events
How to track Multiple Conversion Events
After the base code snippet is installed, you can track multiple conversions within the same web page by making multiple _fbq.push('track') calls for each conversion pixel ids. For example:
_fbq.push(['track','<pixel_id1>',{'value':'10.00','currency':'USD'}]);
_fbq.push(['track','<pixel_id2>']);
How to track In-Page Events
After the base code snippet is installed, you can track in-page actions, such as clicks on a button, by making a _fbq.push('track') call for the conversion pixel through registering different event handlers on an HTML DOM element. For example:
function trackConversionEvent(val, cny) {
var cd = {};
cd.value = val;
cd.currency = cny;
_fbq.push(['track', '<pixel_id>', cd]);
}
<button onClick="trackConversionEvent('10.00','USD');" />
Also, add the facebook pixel tracking code chrome addon and refer the facebook pixel helper page: https://developers.facebook.com/docs/ads-for-websites/pixel-troubleshooting
See my below solution/answer
Facebook tracking code in the current page
(function() {
var _fbq = window._fbq || (window._fbq = []);
if (!_fbq.loaded) {
var fbds = document.createElement('script');
fbds.async = true;
fbds.src = '//connect.facebook.net/en_US/fbds.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(fbds, s);
_fbq.loaded = true;
}
})();
window._fbq = window._fbq || [];
window._fbq.push(['track', 'yourid', {'value':'1.00','currency':'USD'}]);
<!-- Facebook Conversion -->
<script>(function() {
var _fbq = window._fbq || (window._fbq = []);
if (!_fbq.loaded) {
var fbds = document.createElement('script');
fbds.async = true;
fbds.src = '//connect.facebook.net/en_US/fbds.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(fbds, s);
_fbq.loaded = true;
}
})();
window._fbq = window._fbq || [];
window._fbq.push(['track', 'yourid', {'value':'1.00','currency':'USD'}]);
</script>
And the javascript code to call when ajax form submit or button click
<script>
function trackConversionEvent(val, cny) {
var cd = {};
cd.value = val;
cd.currency = cny;
_fbq.push(['track', 'yourid1', cd]);
_fbq.push(['track', 'yourid1', cd]);
}
</script>
and the call the function when ajax called
jQuery(form).ajaxSubmit({
type:"POST",
data: $(form).serialize(),
url:"process.php",
success: function() {
**trackConversionEvent**('1.00','USD');
}
......
Facebook has updated their pixels, so I created my own custom function to call that will dynamically put the parameters together to submit to Facebook.
Step 1. On every page, make sure you've initialised your pixel in the head element of the page.
Step 2. Add this custom function I created (it's a bit verbose as it is the first draft, so I'm sure there are ways to optimise it for your benefit).
triggerFacebookPixel: function(type, price, product_id, product_name, product_category, num_items) {
//See https://developers.facebook.com/docs/ads-for-websites/pixel-events/v2.8#events for documentation
//type = "ViewContent"|"AddToCart"|"Search"|"AddToWishlist"|"InitiateCheckout"|"AddPaymentInfo"|"Purchase"|"Lead"|"CompleteRegistration"
//product_id = Numeric Product ID. String or Integer accepted for single product events, or an array of integers for multiple products.
//price = Decimal/Float number of individual product's price or total price paid in conversion, or the user's status for 'CompleteRegistration'
//product_name = Optional. String of individual product's name or string of search query
//product_category = Optional. String of product category, hierarchy's accepted. E.g. "Clothing > Shirts > Men's > T-Shirts"
//num_items = Optional. Total number of products.
var data = {
value: typeof(price) == 'string' ? parseFloat(price) : price,
currency: 'USD'
}
switch (type) {
case 'Search':
data.content_ids = product_id;
data.search_string = product_name;
if (product_category !== undefined && product_category != '') {
data.content_category = product_category;
}
break;
case 'Lead':
data.content_name = product_name;
data.content_category = product_category;
break;
case 'CompleteRegistration':
data.status = product_id;
data.content_name = product_name;
break;
default:
//Product Specific Calls
//ViewContent|AddToCart|AddToWishlist|InitiateCheckout|AddPaymentInfo|Purchase
if (num_items == 1) {
data.content_ids = [typeof(product_id) == 'string' ? parseInt(product_id) : product_id];
data.content_category = product_category;
data.content_name = product_name;
} else {
data.content_ids = product_id;
}
//"num_items" is only a parameter used in these two types
if (type == 'InitiateCheckout' || type == 'Purchase') {
data.num_items = num_items
}
//"content_type" is only a parameter used in these three types
if (type == 'Purchase' || type == 'AddToCart' || type == 'ViewContent') {
data.content_type = 'product';
}
break;
}
fbq('track', type, data);
}
Step 3. Call that function with the appropriate parameters.
For your thank you pop-up after a purchase, the pixel is fired differently if the user purchases 1 item as opposed to multiple items. Basically, Facebook accepts parameters for product names and categories if it's just one product, but doesn't accept those parameters if it's multiple products.
For the following examples, here is some sample product data of a user purchasing 1 item:
Product Name: "My Super Awesome T-Shirt"
Product ID: 182
Product Category: "Clothing > Shirts > T-Shirts"
Total amount user paid (including shipping/handling & tax): $10.84
And here's the function you'd call on the confirmation:
triggerFacebookPixel('Purchase', 10.84, 182, 'My Super Awesome T-Shirt', 'Clothing > Shirts > T-Shirts', 1);
When a user purchases multiple items, the pixel handles it differently, excluding the product names and categories and only sending their ID's. So let's pretend our user purchased these two items:
Product ID's: 182 and 164 (the shirt and something else)
Total amount user paid (including shipping/handling & tax): $24.75
This is how you'd use the function:
triggerFacebookPixel('Purchase', 24.75, [182, 164], '', '', 2);
For other standard events as defined by Facebook regarding products, you can use this same function for "ViewContent", "AddToCart", "AddToWishlist", "InitiateCheckout", and "AddPaymentInfo". Just change "Purchase" to any of those key words in your call.
The other events aren't necessarily related to products: "Lead", "Search", and "Complete Registration". You can still use this function for those key words like this.
Example: user searched for "blue shirts":
triggerFacebookPixel('Search', 0, [], 'blue shirts');
If you want to pass a product category in the user search function, you can pass that as a string at the end. I can't think of a use-case scenario where you'd know what category the user is searching for. Unless you used this in the event that the product appears in the search results and the user clicked on it from the search page. That might be what this function is actually for but the documentation isn't quite clear on that. If that's the case for you, then simply change the 0 and empty array to the actual values (price and product ID, respectively) of the product that was clicked on from the search results page, and add its category as a string as the last parameter after the search string.
Example: user submitted a form that signed them up to your newsletter:
triggerFacebookPixel('CompleteRegistration', 0, 'Signed Up', 'Newsletter');
Facebook's documentation states that "CompleteRegistration" should be used when a registration form is completed, e.g. complete subscription/signup for a service. The "Signed Up" string is the "status" parameter and the "Newsletter" string is the "content_name" parameter.
Example: user submitted a form that signed them up for a free 30-day trial of some service you offer (so they are now a lead), where the name of the service is "Free 30-Day Trial Service" and it's in the sub-category "Free Trials" under the category "My Services":
triggerFacebookPixel('Lead', 0, 'Free 30-Day Trial Service', 'My Services > Free Trials');
Facebook's documentation states that "Lead" is when a sign up is completed, e.g. click on pricing, signup for trial. I assumed that the name of the service is the parameter "content_name" and the category of the service is the "content_category" parameter.