Ajax request stores old data - javascript

I have a litte problem with my ajax request and I haven't found a solution yet.
What I am trying to accomplish:
I have simple search form, when I submit I send the data to a PHP file which returns the result as json. Then I add the returned data in a clickable list and when I click on one list item I want to display the data in a new div. This actually works fine. Even if I start a new search I get the correct json objects and the list updates as expected but now I have following problem. If I start a new search without refreshing the whole page and again click on a list item, in the console log i see that the new but also the previous data is still kinda stored in the list or wherever and this is the problem because I then display the wrong data if I click on the list items.
I hope you understand my question and I am thankful for every hint. And btw, is my approach even possible or is there a better way to solve this?
Javascript code
$('#searchbar').submit(function(e){
e.preventDefault();
var query = $('#searchQuery').val();
if (query != ''){
loadData();
}else{
alert('Empty searchform!');
}
});
function loadData(){
var query = $('#searchQuery').val();
$.ajax({
type: "POST",
url: "search.php",
data: {'query': query},
dataType: 'json'
}).done(function(res) {
console.log(res);
resetInfos();
generateList(res);
$('.list-group').on('click', '.list-group-item', function(e){
var index = $(this).index();
console.log(res[index].Name);
$('#locationName').text(res[index].Name);
$('#locationAddress').text(res[index].Zip
+ ' '
+ res[index].State);
$('#locationContact').text(res[index].Internet);
init_map(res[index].Latitude, res[index].Longitude);
});
});
}
function resetInfos(){
$('.list-group').empty();
$('#listItems').remove();
$('#searchQuery').val('');
$('#locationName').text('');
$('#locationAddress').text('');
$('#locationContact').text('');
}
function generateList(result){
$.each(result, function(i){
$('.list-group').append('<li class="list-group-item" id="listItems">'
+ result[i].Name
+ ", "
+ result[i].Zip
+ " "
+ result[i].State);
});
}
HTML search form
<form id="searchbar">
<div class="input-group form-group-lg">
<input type="text" id="searchQuery" name="query" class="form-control" autocomplete="off" placeholder="Name, ZIP, State">
<span class="input-group-btn"><button class="btn btn-success btn-lg" id="searchButton" type="submit">Search</button></span>
</div>
<form>

Ok I solved it. I had to remove the click event handler with
$('.list-group').off('click');
in my resetInfos function.

You are using id selector to remove multiple elements.
$('#listItems').remove();
It will only remove the first matched reference. Please add some class to li element and then use class selector to remove.

Related

Jquery keyup event firing more than once

I'm trying to display some content from my database in a div, every time a user types a value into an input box. I'm using jquery to do this. But whenever I type something, once into the input box... the call-back function repeats, four times.
getProducts(){
$('.search-products').on('keyup', function(){
const searchProducts = new SearchProducts();
let search = $.trim($(this).val()); // get search text
if(search!==""){
// let data = {search: search};
let url = '/search-for-products/' + search;
$.ajax({
type: "GET",
url: url,
data: {},
success: function(response){
if(response.success){
searchProducts.showSearchProducts(response.products);
}
}
});
}
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="text" class="form-control search-products" placeholder="What are you searching for ?" aria-label="Username" aria-describedby="basic-addon1" style="color: light grey;">
I'd like your honest opinions on what could be wrong, with my code. Cos, I'm now confused about what to do.
If you've not found why it's added twice, a simple fix is you can remove the listener before adding it again:
$('.search-products').off('keyup').on('keyup', ...)
You can also use namespace events, to not remove other keyup events:
$('.search-products').off('keyup.search').on('keyup.search', ...)
Not many people know that jQuery supports namespace events.

show json file in an alert on click

I have a simple log in at the top of my page that enables a user to enter a code - the code then reads the json file and pulls up the specific user of that code. I do have it showing in the alert, however I want the alert hidden before the user enters the code and displayed if the code is valid. In my json file I have the users code (which is currently named id) and when that is entered their name displays in the alert box. If nothing or an invalid code that is not apart of my code display I want an error alert to display.
This is what I have so far:
the log in text button:
<div class="alert alert-info"><input type="text" id="userName" value> <button type="button" id="loginbtn" class="btn btn-primary btn-md">Login</button></div>
the welcome/login alert:
<div class="alert alert-success" id="loginalert"<strong>Welcome</strong></div>
the error alert:
<div class="alert alert-danger" id="ErrorMessageAlert" <strong>Error</strong>invalid</div>
and the script ive been working on:
$(document).ready(function() {
$("#loginalert").hide();
$("#ErrorMessageAlert").hide();
$("#loginbtn").click(function(event){
$.getJSON('result.json', function(jd) {
var id = $('#userName').val();
for (var i=0; i<jd.user.length; i++) {
if (jd.user[i].ID == id) {
$('#loginalert').html('<p> Welcome: ' + jd.user[i].name + '</p>');
$("#loginalert").show();
}else
{
$("#ErrorMessageAlert").show();
}
);
}
}
});
}); });
A user from the json looks like {"user":[{"ID" : "001","name": "Zara Ali"}
So when the user writes in 001 the alert will display with that name
If the user enters nothing or an invalid code I want the error message to display.
Many thanks
I believe it would be easier to simply use ajax to get the JSON, as it makes your code more readable - that, and indentation and line breaks. The below should work but cannot be tested on Stack Overflow itself as it does not allow AJAX requests. The reason to use this piece of jQuery is that it has some neat built-in features and since this looks like it might be a login form, you might want to post some data over the web as well, which gets easier for later with ajax.
$(document).ready(function(){
$('#loginalert, #ErrorMessageAlert').hide();
$("#loginbtn").click(function(event){
// Every time you click the button, hide all alerts again
$('#loginalert, #ErrorMessageAlert').hide();
$.ajax({
url: 'result.json',
success: function(msg){
for(var i = 0; i < msg.user.length; i++){
if(msg.user[i].ID == id){
$('#loginalert')
.html('<p> Welcome: ' + msg.user[i].name + '</p>')
.show();
} else {
$('#ErrorMessageAlert').show();
}
}
},
error: function(e){
$('#ErrorMessageAlert').show();
}
});
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="alert alert-info">
<input type="text" id="userName" value>
<button type="button" id="loginbtn" class="btn btn-primary btn-md">Login</button>
</div>
<div class="alert alert-success" id="loginalert"<strong>Welcome</strong></div>
<div class="alert alert-danger" id="ErrorMessageAlert" <strong>Error</strong>invalid</div>
There also seems to be a bit of a problem here in logic - can you have multiple users logged in at once in the same place? If not, then why are we looping through the results? You should return just one user, not nested. If you now get back multiple users, then only the last users name will be displayed, and that's odd. I would either change your JSOn to return only one user by default, or modify the javascript to only check for one:
success: function(msg){
if(msg.user[0] && msg.user[0].ID == id){
$('#loginalert').html('<p> Welcome: ' + msg.user[0].name + '</p>').show();
} else {
$('#ErrorMessageAlert').show();
}
}
The major thing is structure, though. Use tabs, line-breaks, and any kind of visual information to show what step nests in what other step, making your code easier to read at a glance.

Add to cart adding first item

I have a simple cart where I can add items on the fly and it update via AJAX. Issue being I am pulling my items from the database but when I click 'add to cart' it populates the cart but with the first item only so no matter which one I click it adds item 1.
I am looping through a result and getting the row:
while ($row = mysqli_fetch_array($r)) {
echo '
<div class="items" id="item">
'.$row["prod_name"]. '';
echo "
<div class='product_display'>
<p><img src='../admin/uploads/".$row['file_upload']."'></p>";
echo"
<input type='button' value='Add To CART' onclick='cart(\"item\");' ";
echo'
<p>Price - '.$row["prod_price"]. '</p>
<input type="hidden" id="item_name" value="'.$row["prod_name"]. '">
<input type="hidden" id="item_price" value="'.$row["prod_price"]. '">';?>
<?php echo'
</div>
</div>
';
}
The echo's really need cleaning up but they confuse me so much!
I am using a little bit of JS to do the AJAX:
$(document).ready(function(){
$.ajax({
type:'post',
url:'store_items.php',
data:{
total_cart_items:"totalitems"
},
success:function(response) {
document.getElementById("total_items").value=response;
}
});
});
And my JS does the rest:
function cart(id)
{
var ele=document.getElementById(id);
var img_src=ele.getElementsByTagName("img")[0].src;
var name=document.getElementById(id+"_name").value;
var price=document.getElementById(id+"_price").value;
$.ajax({
type:'post',
url:'store_items.php',
data:{
item_src:img_src,
item_name:name,
item_price:price
},
success:function(response) {
document.getElementById("total_items").value=response;
}
});
}
function show_cart()
{
$.ajax({
type:'post',
url:'store_items.php',
data:{
showcart:"cart"
},
success:function(response) {
document.getElementById("mycart").innerHTML=response;
$("#mycart").slideToggle();
}
});
}
I thought I would share it all so you can see - but the main issue is the fact it just adds item 1 form the list no matter which one you click on - I am getting no errors and the console is giving me nothing?
It is because you are using the same id for all your items. IDs should only be used once per page, and in cases where you are using it multiple times, document.getElementById(id) will only get the first one that it finds which is why you keep on getting the first item in the list only.
You can give each item different ids and pass that id to the cart function. Or to make things simplier, use event delegation (since you're already using jQuery) to listen for clicks on the Add To Cart button so that you don't have to use the onclick attribute anymore. You can do it like this:
$(document).on('click', 'ADDTOCARTBUTTONSELECTOR', function() {
var element = $(this).closest('.items');
var image = element.find('img')[0].src;
var name = element.find('NAMESELECTOR').val();
var price=document.find('PRICESELECTOR').val();
// the ajax part follows here
});
The ADDTOCARTBUTTONSELECTOR, NAMESELECTOR, and PRICESELECTOR are just placeholders to the actual selectors to those elements, and just replace them appropriately to select the proper elements.

Flickr API tag search (jQuery/ajax)

So I have a simple search form at the top of my document which is ment for tags. It looks like this:
<div id="search">
<form id="srch">
<input type="text" placeholder="No filthy keywords pls." id="sbx"/>
<i class="fa fa-search"></i>
</form>
</div>
And I want the user to write a tag into the "search" field and when he presses the submit button it gets the photos based on the tag he supplied and fetches photos from flickr and fills a #container div with them. The jQuery I have so far looks like this:
var searchTerm = $("#sbx").val();
var Flickurl = "https://api.flickr.com/services/rest/?method=flickr.photos.search&api_key=376b144109ffe90065a254606c9aae3d&";
var tags = "&tags=" + searchTerm;
var tagmode = "&tagmode=any";
var jsonFormat = "&format=json";
var FinalURL = Flickurl + tags + tagmode + jsonFormat;
$(document).ready(function() {
$("#btn").click(function(event){
$.getJSON('FinalURL', function(photo) {
$('#content').append('<img src="' + 'https://www.flickr.com/photos/' + photo.owner + '/' + photo.id + '"/>');
});
});
});
I cannot find any help anywhere, I'm doing this as a schools project and I have never, ever done anything with API's I think I'm misunderstanding something in the jquery and api documentation because this is not doing anything at all lol..
I will be super happy if there is anyone who could help me with this, I feel like the code should be good but maybe I'm missing something small.. ?
You are fetching the string 'FinalURL', which will be resolved to CURRENT_URL/FinalURL, try this
$.getJSON(FinalURL, ... (without the quotes ')
Ok i found some other errors too.
Change your var jsonFormat to this "&format=json&nojsoncallback=1" to get jsonrawdata from the api.
The json returned isn't one photo, it's a list of all photos, so to access one photo you have to do this: response.photos.photo[NUMBER]
Your url is pointing to a flickr page and not to an image source, it should be like this: https://farm{farm-id}.staticflickr.com/{server-id}/{id}_{secret}.jpg
I fixed your errors in this fiddle: JSFiddle
Something like this will work. You just needed to change how you were populating the url queries into a javascript object.
http://jsfiddle.net/669jy9am/
Obviously this won't work on JSFiddle, but if you put that into your own page, it should work.
<div id="search">
<form class="search--form">
<input type="text" placeholder="No filthy keywords pls." id="sbx" />
<button type="submit" id="btn">Search<i class="fa fa-search"></i>
</button>
</form>
function searchFlickr() {
var searchTerm = $("#sbx").val();
var Flickurl = "https://api.flickr.com/services/rest/?method=flickr.photos.search&api_key=376b144109ffe90065a254606c9aae3d&";
$("form").submit(function (event) {
event.preventDefault();
var searchTerm = $('#sbx').val();
$.ajax({
url: 'Flickrurl',
data: {
format: "json",
jsoncallback: 1,
tags: searchTerm
},
}).done(function (data) {
//Populate the images with the data
});
});
}
$(document).ready(function () {
searchFlickr();
});

jquery ajax method being repeated even though click event not correct

I have some ajax on my web page, that is triggered via a click event, the javascript in question looks like this,
$('.career_select .selectitems').click(function(){
var selectedCareer = $(this).attr('id');
$.ajax({
type: 'POST',
url: '/roadmap/step_two',
data: 'career_choice='+selectedCareer+"&ajax=true&submit_career=Next",
success: function(html){
$('.hfeed').append(html);
buildSelects();
$('.grade_options .selectitems').addClass('select_1')
}
});
});
This part of the ajax request works fine. What happens on success is that I load in another view into my page, this view has some more user interaction that fires some more ajax however, it just fires the previously used method, where as it should be doing the following,
$('.grade_options .selectitems').click(function(){
var selectedGrade = $(this).attr('id');
alert(selectedGrade);
})
The HTML+PHP looks like this,
<div class="grade_options">
<input value="" name="grade" class="customselect" type="hidden">
<div class="iconselect">Have you got any of the following?</div>
<div style="display: none;" class="iconselectholder">
<div class="selectoptions">
<div id="1" class="selectitems hoverclass selectedclass select_1">
<span>Accountant</span>
</div>
<div id="2" class="selectitems">
<span> Grade D's at GCSE including English and Maths</span>
</div>
<div id="3" class="selectitems">
<span>3 GCSE's at grade B and 3 GCSEs at grade C or equivalent and you must have achieved at least a grade C in GCSE English Language & B in Maths</span>
</div>
</div>
</div>
<noscript>
<input type="submit" value="Next" name="submit_grades" class="arr" />
</noscript>
</div>
The .selectitems get created from a select menu using this plugin,
$.fn.customSelect = function() {
// define defaults and override with options, if available
// by extending the default settings, we don't modify the argument
return this.each(function() {
obj = $(this);
obj.after("<div class=\"selectoptions\"> </div>");
obj.find('option').each(function(i){
$(".selectoptions").append("<div id=\"" + $(this).attr("value") + "\" class=\"selectitems\"><span>" + $(this).html() + "</span></div>");
});
obj.before("<input type=\"hidden\" value =\"\" name=\"" + this.name + "\" class=\"customselect\"/><div class=\"iconselect\">" + this.title + "</div><div class=\"iconselectholder\"> </div>")
.remove();
$('.iconselectholder').hide();
$(".iconselect").click(function(){
$(".iconselectholder").toggle("slow");});
$(".iconselectholder").append( $(".selectoptions")[0] );
$(".selectitems").mouseover(function(){
$(this).addClass("hoverclass");
});
$(".selectitems").mouseout(function(){
$(this).removeClass("hoverclass");
});
$(".selectitems").click(function(){
$(".selectedclass").removeClass("selectedclass");
$(this).addClass("selectedclass");
var thisselection = $(this).html();
$(".customselect").val(this.id);
$(".iconselect").html(thisselection);
$(".iconselectholder").toggle("slow")
});
});
// do the rest of the plugin, using url and settings
}
I am struggling to see any reason as to why my second ajax request is running the method of the first ajax request.
Your code seems somewhat incomplete, but I think I can help you.
Where is the class .career_select in the HTML+PHP example you have given? My guess is that .career_select is wrapping .grade_options due to your append:
$('.hfeed').append(html) am I correct? .grade_options was part of the html that got appended right?
If I am correct, then the newly appended HTML would not have had event handlers tied to it ahead of time and hence your second event handler is not firing. I think there are two things you can do:
Declare the new event handler for $('.grade_options .selectitems') in the success function of the first event handler AFTER the append.
If that doesn't work then just do what Paul Sweatte instructed you to do (look at the comments), unbind the original click event in the success callback or if you are sure it is a one-off thing, take a look at jQuery's $(selector).one().
I hope this helps. If the second one works, please remember to give points to Paul Sweatte's comment.

Categories

Resources