Ive been desperately trying to get this to work.
Iknow there are probably better ways to do this other than the way I am trying but its for an assignment and has to be done this way.
I am creating a simple shopping cart/ the cart does not have to add a total just get the items inside of the panel (if anyone knew how to add the price also that would be brilliant but not 100% necessary)
So I have displayed items of json using json and ajax, on page ready the items are on show as so (there are about 12 items):
so I have the panel hidden, when the user clicks on a button (the blue button) I want the json information and the json price to appear inside the panel.
here is a snip of one of the items from my json file (which is called result.json:
{
"appleitems":[
{
"Product_id":"Iphone5",
"Information":"Iphone 5 64GB",
"Imgpath":"image/iphone5.jpg",
"Price":"200.00"
}
]
}
This ishow my items are displayed:
$.getJSON('iproducts.json',function(products){
var output = "";
$.each(products.appleitems, function(i, product) {
output +=
"<div class=\"col-xs-12 col-sm-6 col-md-3\"><div class='panel panel-default'><div class='panel-footer'><h4 class='text-center'>"
+ products.appleitems[i].Product_id
+ "</h4></div>" + "<img src ='" + products.appleitems[i].Imgpath + "' style='width:100%;height:250px; display: block;' id='appleinfo_"
+ products.appleitems[i].Product_id + "' /><h5 class='text-center'>" + products.appleitems[i].Information
+ "</h5><div class='panel-footer'>`<button class='btn btn-primary btn-block' id='btnadd'>£" + products.appleitems[i].Price+"</button>`</div></div></div>";
});
$("#container").html(output);
});
and you will notice the button that I want clicked to display the json is btnadd:
<button class='btn btn-primary btn-block' id='btnadd'>£" + products.appleitems[i].Price+"</button>
so when the user clicks btn add I want the json "information" and "price" to display inside of the pannel cart:
<div class="panel panel-default">
<div class="panel-body" id="cart"></div>
I have started the script for this:
$(document).ready(function() {
//Hide alert when page loads
$("#cart").hide();
//get the item into the panel
$("#btnadd").click(function(event){
$.getJSON('result.json', function(add) {
...
});
});
});
First of all, You are having same Id value for all the buttons(inside the loop). Duplicate Id's are not valid. So may be you can remove that and add a css class to the button for the jQuery selection. Also i would recommend keeping the price and information in HTML5 data attributes on the button for easier read.
var output ="";
$.each(products.appleitems, function(i, product) {
output += "<div><div>"
output +="<button class='btn btn-primary btn-block addBtn' data-info='"+
product.Price +"' data-price='"+
product.Information +"'>£" + product.Price+"</button>";
output +="</div></div>";
});
And listen to the click event on this specific css class
$(function(){
$(document).on("click",".addBtn",function(e){
e.preventDefault();
var _this=$(this);
var c=_this.data("info") + " " +_this.data("price");
$("#cart").html(c);
});
});
Here is a working sample
Related
I'm working on a website that makes a call to a database. It takes the JSON from the database and loops through a specific node -- appending HTML code to a div tag, which creates a Card for each database entry. I want to be able to have a Bootstrap Popover (or Tooltip) that appears when a Card is clicked (or hovered over if Tooltip). The Cards that are generated within the function fail to produce a Popover or Tooltip at all. If I append the same HTML code outside the function using JQuery, it works just fine. I'm unsure what is happening here.
Here's the function that loops through the database JSON and creates a card for each child.
function getWeekEvents(day, id) {
return firebase.database().ref(day).once('value').then(function(snapshot) {
var data = snapshot.val();
for (item in data) {
var event = data[item]["event"];
var loc = data[item]["loc"];
var time = data[item]["time"];
$("#" + id).append("<div class='card border border-primary week-cards-ann event-style' data-toggle='popover' data-content='Content' data-placement='right'>" +
"<div class='card-body my-lg-n3'>" +
"<div class='card-text my-lg-n1 float-left ml-lg-n3'>" +
"<p>" + event.substring(0,10) + "...</p>" +
"</div>" +
"</div>" +
"</div>");
}
});
}
The code below is outside any function and works just fine. It creates a card in the same way, but the Popover works.
$("#tuesday").append("<div class='card border border-primary week-cards-ann event-style' data-toggle='popover' data-placement='top' title='Hello'>" +
"<div class='card-body my-lg-n3'>" +
"<div class='card-text my-lg-n1 float-left ml-lg-n3'>" +
"<p>" + "...</p>" +
"</div>" +
"</div>" +
"</div>");
And I also have this part that is required for Popovers to work.
$(function () {
$('[data-toggle="popover"]').popover()
});
I also tried creating a Tooltip in the same way, instead of a Popover, but it resulted in the same problem. This lead me to believe that there may be something happening with the data-toggle attribute? I could be wrong. Does anyone have any thoughts?
I dynamically create bootstrap 4 columns based on an array length. My array has 4 objects in it so it is printing 4 col-sm-3s.
That is being accomplished with this js:
for (var i = 0; i < allChars.length; i++) {
var num = Math.floor(12 / allChars.length);
$('#allCharsRow').append("<div class='col-sm-" + num + "' id='char-col" + i + "' data-toggle='tooltip' data-placement='top' title='" + allChars[i].toolTipTitle + "'><div class='card'><div class='card-header text-center text-white'> <h4 class='display-6'>" + allChars[i].class + "</h4></div>" + allChars[i].mainGif + "<div class='card-footer'><button class='btn btn-link text-white btn-block' id='charBTN" + i + "'>Choose " + allChars[i].class + "</button></div></div></div></div>")
}
That is all well and good until one of the objects is selected. I have a .fadeOut on button click.
$('#char-col0').fadeOut('slow');
So whichever column is chosen, that whole column disappears. Then the row recalculates and it doesn't look as good. Is there a way I can get the row to not recalculate - i.e. meaning can I get it to think there's still a column there but hide the contents of that column from the user?
I've tried not creating the columns dynamically. I've tried .hide('slow') instead of fadeOut...
.hide() transitions the element's CSS to display: none, which means it is completely removed from the page. What you really want to do is keep the element on the page (so that it keeps taking up space), but make it invisible to the user. In other words, you want to change its opacity to 0:
.fadeTo( "slow", 0 )
Here is the full API reference: https://api.jquery.com/fadeTo/
I have a problem with duplicate calls being sent onclick of a link, which includes the previous call data if they were made.
Here is the construction of the link in question.
for (var key in res) {
var followers = res[key].followers;
var totalposts = res[key].totalposts;
var id = res[key].id;
var name = res[key].name;
var titles = "";
titles = '<ul class="titles">';
if (typeof res[key].titles === "object") {
for (var index in res[key].titles) {
var url = res[key].titles[index].st_url;
titles += '<li><div class="ui grid"><div class="ui fourteen wide column">\u2022 '+url+'</div><div class="ui two wide column"><a title"Remove this post" href="#" onclick="showRemPost('+id+', \''+url+'\', \''+name+'\')" id="remPostButton"><i class="ui remove grey circle icon"></i></a></div></div></li>';
}
}
titles += "</ul>";
html +=
'<div class="ui eight wide column"><div class="ui segment" data-id="' + id + '" id="list' + id + '">' +
'<div class="listTitle"><h4 class="left">' + name + '</h4><div class="right"><i class="edit icon"></i> <i class="remove icon"></i></div><div class="clear"></div></div>' +
'<div>' + titles +
'</div>' +
'<div class="footList"><div class="left"><p>Followers: <span class="follow">'+followers+'</span>' +
'<br/>Posts: <span class="post">'+totalposts+'</span>' +
/*'<br/>Upvotes: <span class="upvote">'+res[key].upvotes+'</span>' + */
'</p></div>' +
'<div class="right"><i class="ui add blue circle icon"></i></div></div><div class="clear"></div>' +
'</div></div>';
}
Then I have this code for the function call:
showAddPost = function(id, lname){
//do stuff
console.log("\nshowAddPost function called");
}
console.log("\nshowAddPost function called"); is showing 1 time on first click, then 2x on second click, and so on. Each time, I get the data from the previous click.
Since there are multiple links to click, any link clicked after another, will send all previous clicks and their data, as events to the showAddPost.
Ex: 1st click has "ID": "1" and "name": "One". These are sent. On the second link and second click, "ID": "2" and "name": "Two", which should only call once, and send only the Two data, but it sends the previous data, "1:One" to the function call showAddPost, then it send a second call to showAddPost for the actual link clicked with "2:Two". And the if I click on a third link, the same or different, it send the previous two data to the function.
Is the only way to resolve this by moving the onclick from the HTML to it's own .on() handler and then getting the data through data- attributes? Or can I get the data passed in an easier way with the .on() handler? Can I still use onclick and resolve this problem?
All of this is in a separate namespace, not global scope.
Thank you anyone for any help.
You are most likely not closing the a tags.
So you end up with
<a href="#" onclick="showAddPost('+id+', \''+name+'\')" class="addPostButton">
<a href="#" onclick="showAddPost('+id+', \''+name+'\')" class="addPostButton">
...
Nesting a tags is invalid. The issue in your case is that the inner a tags will trigger all the previous since the click event bubbles upwards.
update after updated code and comment
Actually yes, the line
'<div class="right"><i class="ui add blue circle icon"></i></div></div><div class="clear"></div>' +
has wrong matching on opening/closing tags. Lets break it down to see
<div class="right">
<a href="#" onclick="showAddPost('+id+', \''+name+'\')" class="addPostButton">
<i class="ui add blue circle icon"></i>
</div> <!-- << this here does not match a div, it should be an a -->
</div>
<div class="clear">
</a> <!-- << this here probably belong on the previous group -->
</div>
So I have a get json function that makes items appear on my page, there is a button with json included inside of it that when is clicked I want the item to appear inside an alert (its called cart) - its going to be a simple shopping cart that is hidden on page ready/load. So when the user clicks this button parts of my json file appear inside of the alert, like a shopping cart, If there can be a total to calculate the price this would be good but is not necessary.
So this is my script to get the json and display it on my page :
$.getJSON('iproducts.json',function(products){
var output = "";
$.each(products.appleitems, function(i, product) {
output +=
"<div class=\"col-xs-12 col-sm-6 col-md-3\"><div class='panel panel-default'><div class='panel-footer'><h4 class='text-center'>"
+ products.appleitems[i].Product_id
+ "</h4></div>" + "<img src ='" + products.appleitems[i].Imgpath + "' style='width:100%;height:250px; display: block;' id='appleinfo_"
+ products.appleitems[i].Product_id +
"' /><p class='lead text-justify'>" + products.appleitems[i].Information
+ "</p><div class='panel-footer'><button class='btn btn-primary btn-block' id='btncart'>£" + products.appleitems[i].Price+"</button></div></div></div>";
});
$("#container").html(output);
});
as you will notice this is the button I am talking about:
<div class='panel-footer'><button class='btn btn-primary btn-block' id='btncart'>£" + products.appleitems[i].Price+"</button></div>
the price is displayed inside of the button.
This is a snip (one of the products, there are about 12 products in total) from my json file:
{
"appleitems":[
{
"Product_id":"Iphone5",
"Information":"Iphone 5 64GB",
"Imgpath":"image/iphone5.jpg",
"Price":"200.00"
}
]
}
This is the alert I want the name and price to display in when the button is clicked:
<div class="alert alert-warning" id="cart"></div>
Here is a bit of a clue from a previous script I worked on, when the user entered their name/ login details (from the json) and they matched their name, picture and details would appear in the welcome alert, I also had a hide button inside this alert that then hid the welcome alert and this is how I got it to work ( could be quite similar to this only .show():
$(document).ready(function() {
//Hide alert when page loads
$("#loginalert").hide();
$("#invalid").hide();
$("#loginbtn").click(function(event){
$.getJSON('result.json', function(jd) {
var id = $('#userName').val();
var name = $('#userName2').val();
var valid = false;
$('#loginalert').html('<img src="' + jd.user[i].imgpath + '"><br><p> Welcome: ' + jd.user[i].name + '</p><button type="button" id="btnhide" class="btn btn-primary btn-md">Hide</button>');
//show the alert after loading the information
$("#loginalert").stop().fadeIn('slow').animate({ opacity: 1.0 }, 3000)
$('#invalid').hide();
$('#btnhide').on('click', function(e){
e.preventDefault();
$('#loginalert').hide();
});
}
}
if (!valid) {
$('#invalid').fadeIn('slow');
$('#loginalert').hide();
Kind Regards
So on button click you want to update the alert div with it's price.
Here is a code block explaining things you need.
According to this html
$('.btn-block').click(function(e){
//alert($(this).attr("value")); //get value of button
$("#cart").empty(); //clear div every time on click
$("#cart").html($(this).attr("value")); //this will update div with value of button.
var product_information = $(this).closest("div").prev("p").html();//This will get you product info
});
I have added some explanation as comment.This are self explanatory.
Important
I notice you assign hardcore id in each loop in button which is not correct.You should always assign dynamic id as id cannot be same.
My application successfully creates elements and assigns them different (increasing) IDs.
Now my issue relies when the user deletes these elements (because they have the option to delete as well as create), the consistency of these IDs get broken therefore my application doesn't run well.
This Fiddle represents what I have so far. Just a textbox that appends its value and a few other elements inside a collapsible as many times as the user wants (For some reason my fiddle doesn't increment the alert value, but it works fine on my platform).
SCRIPT (Sorry the txt variable is too long)
$('#Add').click(function () {
if ($("#MedNameStren").val() != "") {
var value = $("#MedNameStren").val();
var noOfMeds = $('#NoOfMedicines').val();
//to check current value
alert(noOfMeds);
var text = '<div data-role="collapsible" data-collapsed="true" data-iconpos="left" data-content-theme="e">' + '<h2>' + desc + '</h2>' + '<div class="ui-grid-a">' + '<div class="ui-block-a" style="width:25%; margin-right:3%;">' + '<input id="quantity' + noOfMeds + '" class="quantity" type="text" placeholder="Quantity" />' + '</div>' + '<div class="ui-block-b" style="width:70%; margin-right:2%;"">' + '<textarea id="directions' + noOfMeds + '" class="directions" cols="40" rows="4" placeholder="Directions given by your GP." ></textarea>' + '</div>' + '</div>' + '<button key="' + vpid + '">Remove</button>' + '</div>';
$("#medListLi").append(text);
$('button').button();
$('#medListLi').find('div[data-role=collapsible]').collapsible();
$('#medListLi li').listview("refresh");
$('#medListLi').trigger("create");
document.getElementById("manuallyName").value = "";
noOfMeds++
$("#NoOfMedicines").val(noOfMeds);
}
else {
alert('Please Provide Medicine Name')
}
});
I am using a counter that neatly increments the ids of quantity and description like:
quantity0
quantity1
quantity2
..and so on, but once the following script is called...
//Deletes colapsible sets (Medicines) from the selected List
$('#medListLi').on('click', 'button', function (el) {
$(this).closest('div[data-role=collapsible]').remove();
var key = $(this).attr('key');
localStorage.removeItem(key);
var noOfMeds = $('#NoOfMedicines').val();
noOfMeds--
$("#NoOfMedicines").val(noOfMeds);
//location.reload();
});
depending on which element (collapsible) is deleted, the IDs stop being consistent. For example if the collapsible with id="quantity1" is deleted then the counter will go back to 1 (currently 2) and on the next addition the respective collapsible will get an id that's already taken, and unfortunately I don't need this to happen.
Maybe I'm making this sound more complicated that it is, but will appreciate any suggestions or ideas to solve this issue (if possible).
If more information is needed, please let me know.
Was brought to my attention that creating and deleting dynamic IDs can be done but keeping up with consistency of these IDs can be very tricky to work around it.
I've solved my own problem by simply creating a function that would keep count of the IDs from the amount of collapsibles inside my list and "renewing" the ID numbers on each Add and Delete.