Ajax-Post data again AFTER success - javascript

So I have got a small application that check metrics for domains that are valuable for SEO. I establish a connection with API and process them to get the relevant data.
Everything works great there and I do get my data, problem is with Javascript main.js that processes that data.
So my main idea is that I have a select input that corresponds to specific API calls, then a textarea where you paste your links. All works great, and I manage to get the response using ajax and build a relevant view corresponding to a specific method selected.
When ajax responds with success, I fetch data, parse it and make relevant function calls. When page is built, on top I need to have a small select box that would make user to select different method and would retrieve data for the same links. After success I have built a input that correspond to the same select used on main page.
And my question is How can i send data again?
So, here is the code
$("#parseLink").on("click", function () {
var textBox = $("#linkInput").val();
var method = $("#select").val();
var newTextBox = textBox.split("\n");
var methodsList = {
"Social Values": "GetValueSocialSpread",
"Social Visibility": "SocialGetValueVisibility",
"Organic Keyword Count": "GetCountDomainKeyword",
"Seo Visibility": "SeoVisibilityWorld"
};
var selectedApi = methodsList[method];
var dataToSend = {
url: newTextBox,
api: selectedApi
}
$("#container").replaceWith("<div class='containter text-center'><h1>Loading...</h1><i class='fa fa-spinner fa-pulse fa-5x'></i></div>");
function mainFunc() {
$.ajax({
type: "POST",
url: "../parser.php",
data: {
data: JSON.stringify(dataToSend)
},
success: function (response) {
//remove loading
$("div.text-center").remove();
$("div.main_holder").append("<div class='container'><div class='row'><div class='pull-right'><button id='export' type='button' class='btn btn-info'>Export</button></div></div></div>");
$("div.main_holder").append("<div class='container'><div class='row'><select class='form-control' id='select'><option>Social Values</option><option>Social Visibility</option><option>Organic Keyword Count</option><option>Seo Visibility</option></select></div></div>");
var result = JSON.parse(response);
var jsonObject = result;
urlArray = [];
$.each(result, function (k, v) {
urlArray.push(k);
});
if (method === "Social Values") {
socialValues(result, urlArray);
} else if (method === "Social Visibility") {
socialVisibility(result, urlArray);
} else if (method === "Organic Keyword Count") {
organicKeyWordCount(result, urlArray);
} else if (method === "Seo Visibility") {
seoVisibility(result, urlArray);
}
}
});
}
});
I tried calling ajax function again, not working... it probably has a simple solution(hopefully)
I am opened to suggestions! And please tell me if you need more elaborate explanation! Was doing it all night :))

Related

jQuery error in client post response - POST HTTP/1.1" 400

I can't figure out what is wrong with my code and I'm not really good with jQuery.
I'm trying to build HTML form will hold cars data. It's based on this form:
HTML source code is here.
Form data is sent on button click on the end back to program.
I upgraded that form with cascading manufacturer (proizvodjac in code) and car models droplist based on this code. But it's not working.
I keep receiving HTTP 400 which would mean that my POST call from client is malformed.
Here is my jQuery functions:
$(function () {
var carsdata = {"alfaromeo":["mito","156","147","giulietta","159","166","146"],"audi":["a3","a4","a6","a5","80","a1","q3","a8","q5"],"bmw":["320","116","x3","316","318","118","530","x1","520","x5","525","330","120","323","serija 1"],"chevrolet":["spark","lacetti","captiva","aveo","cruze"],"citroen":["c4","c4 grand picasso","c3","c5","c4 picasso","xsara","berlingo","c2","xsara picasso","saxo","ds5","c1"],"fiat":["brava","bravo","panda","grande punto","stilo","punto","punto evo","doblo","500","tipo","uno","coupe"],"ford":["c-max","fiesta","focus","mondeo","fusion","ka","escort"],"honda":["civic","accord","cr-v"],"hyundai":["getz","i10","i20","atos","i30","coupe","elantra","accent","santa fe","ix35","tucson"],"kia":["rio","pro_cee'd","sportage","cee'd","pride","sorento"],"mazda":["3","2","323 f","626","6","cx-5","323","premacy","5"],"mercedes":["a-klasa","c-klasa","e-klasa","b-klasa","124"],"mercedes-benz":["e-klasa","clk-klasa","c-klasa","s-klasa","190","a-klasa","b-klasa","c t-model","ml-klasa","w 124","124"],"nissan":["qashqai","x-trail","note","primera","micra","juke","almera"],"opel":["corsa","astra","zafira","meriva","vectra","insignia","mokka","tigra","combo","astra gtc","kadett"],"peugeot":["308","207","206","306","106","307","208","406","508","407","partner","3008","405"],"renault":["thalia","clio","scenic","grand scenic","kangoo","captur","megane grandtour","megane","laguna","5","megane break","twingo","modus","kadjar","megane classic","espace","megane scenic","megane coupe","megane sedan"],"seat":["toledo","leon","ibiza","altea","cordoba"],"skoda":["fabia","octavia","120","superb","felicia","rapid"],"smart":["fortwo"],"toyota":["corolla","yaris","auris","avensis","rav 4","land cruiser"],"vw":["polo","golf v","golf iv","golf vii","passat","golf vi","jetta","passat variant","caddy","sharan","tiguan","golf variant","golf ii","vento","golfplus","golf iii","bora","touran","touareg","up!"]};
var proizvodjac = $('<select id="proizvodjac"></select>');
var model = $('<select id="model"> </select>');
$.each(carsdata, function(item, key) {
proizvodjac.append('<option >' + item + '</option>');
});
$("#containerProizModel").html(proizvodjac);
$("#proizvodjac").on("change", function(e) {
var item;
var selected = $(this).val();
if (selected === "alfaromeo") {
item = carsdata[selected];
} else {
item = carsdata[selected];
}
$(model).html('');
$.each(item, function(item, key) {
model.append('<option >' + key + '</option>');
});
});
$("#containerProizModel").append(model);
$("button#predict").click(function(e){
e.preventDefault();
/*Get for variabes*/
var kilometraza = $("#kilometraza").val(), godina_proizvodnje = $("#godina_proizvodnje").val();
var snaga_motora = $("#snaga_motora").val(), vrsta_goriva = $("#vrsta_goriva").val();
/*create the JSON object*/
var data = {"kilometraza":kilometraza, "godina_proizvodnje":godina_proizvodnje, "proizvodjac":proizvodjac, "model":model, "snaga_motora":snaga_motora, "vrsta_goriva":vrsta_goriva}
/*send the ajax request*/
$.ajax({
method : "POST",
url : window.location.href + 'api',
data : $('form').serialize(),
success : function(result){
var json_result = JSON.parse(result);
var price = json_result['price'];
swal('Predviđena cijena auta je '+price+' kn', '','success')
},
error : function(){
console.log("error")
}
})
})
})
Comments and explanations are in the code.
On server side:
Server is expecting user_input dictionary which is built from variables returned by POST request. Here is how API method looks:
#app.route('/api',methods=['POST'])
def get_delay():
result=request.form
proizvodjac = result['proizvodjac']
model = result['model']
godina_proizvodnje = result['godina_proizvodnje']
snaga_motora = result['snaga_motora']
vrsta_goriva = result['vrsta_goriva']
kilometraza = result['kilometraza']
user_input = {'proizvodjac':proizvodjac,
'model':model,
'godina_proizvodnje':godina_proizvodnje,
'snaga_motora':snaga_motora,
'vrsta_goriva':vrsta_goriva,
'kilometraza':kilometraza
}
print(user_input)
a = input_to_one_hot(result)
price_pred = gbr.predict([a])[0]
price_pred = round(price_pred, 2)
return json.dumps({'price':price_pred});
Error from Google Chrome Developer Console:
which is pointing to:
EDIT 1:
I don' know how to pass proizvodjac and model to onClick function. See what happens on breakpoint:
XHR on Network tab:
HTML form is being filled with data OK only manufacturer and model are not passed to onClick:
EDIT 2:
Getting closer to solution. I've added :
var proizvodjac = $("#proizvodjac").val()
var model = $("#model").val()
as suggested and now all variables are successfully passed!
But I still get error 400 as final ajax POST call is getting stuck somwhere..
EDIT 3:
changed from
data : $('form').serialize()
to
data = data
AJAX method receives everything ok:
Still it doesn't work.
There are two main issues here:
1) you aren't getting the values from two of your fields correctly. You need to add
var proizvodjac = $("#proizvodjac").val()
var model = $("#model").val()
inside the $("button#predict").click(function(e){ function.
2) You're collecting all these values and putting them into your data variable...but then you aren't doing anything with it. Your AJAX request is configured as follows in respect of what data to send:
data : $('form').serialize()
The serialize() function automatically scoops up all the raw data from fields within your <form> tags. In your scenario, if you want to send a custom set of data (rather than just the as-is contents of the form) as per your data object, then you simply need to change this to
data: data
so it sends the information from that object in the POST request instead.

AJAX query not always updating information consistently

I am experiecing some issues with AJAX updating the page. The actual data in the database is updated but this is not always reflecting in real time on the web page.
For example, I have the following event:
$("#add_note").click(function(e) {
//e.preventDefault();
$("#add_note_form").validate({
rules: {
contact_note: {
required: true
}
},
submitHandler: function(form) {
contact.modal_update({
'obj' : $('#add_note_form'),
'uri' : '/contact/add_note/'
});
}
});
});
This function when a new note is created calls a callback to validate the form fields first and then if successful calls a callback inside a seperate class to conduct the update. See the modal_update class below:
// Update modal
this.modal_update = function(data)
{//
// Declare a few variables for the data object we've received
obj = data.obj // The form element to serialize
uri = data.uri;
// Get the form ID from the data-target attribute
id = obj.attr('data-target');
// URL to send to
url = this.site_url + uri + id;
// The form object
this.post_data(obj.serialize(),url);
// Hide Modal
obj.closest('.modal').modal('hide');
// Refresh
this.refresh();
}
This then figures out the correct route to ajax and calls a ajax call back inside the same class:
// AJAX post
this.post_data = function(obj,uri)
{
$.ajax({
data: obj,
dataType: 'json',
type: 'post',
url: uri,
headers: { "cache-control": "no-cache" },
cache: false,
success: function (response) {
if (response.success == true)
{
$("#alert_success .msg").html(response.message);
$("#alert_success").fadeIn(200).delay(2000).fadeOut(200);
}
else
{
$("#alert_error .msg").html(response.error);
$("#alert_error").fadeIn(200).delay(2000).fadeOut(200);
console.log(response.error);
}
}
});
}
I am then running another class callback to "refresh" the data in all the elements on the page:
this.refresh = function()
{
// Refresh the ajax requests
this.get_contact_data();
this.get_notes();
this.get_contact_log();
this.get_contact_tasks();
}
This class re loads the functions which run on page load to get the inial data into the tables/fields on the page. See "get_notes" below:
// Get notes
this.get_notes = function()
{
// Get all notes and populate table
var log_uri = this.site_url + "/contact/get_notes/" + this.contact_id;
this.get_data(log_uri,function(data) {
notes = $("#contact_notes ul");
notes.empty("");
// Populate the contact fields, assuming there is a result to play with
if (data != false) {
//alert(JSON.stringify(data));
$("#notes-tab .count").html("(" + data.length + ")");
$.each( data, function( key, value ) {
notes.append("<li class='list-group-item' modal-id='editNoteModal' data-target='" + value.ID + "'><div class='row'><div class='col-lg-3'><i class='fa fa-sticky-note mr-3'></i>" + value.timestamp + "</div><div class='col-lg-7'>" + value.note + "</div><div class='col-lg-2'><a href='#' class='edit mr-3'><i class='fa fa-edit mr-1'></i>Edit</a><a href='#' class='delete'><i class='fa fa-times mr-1'></i>Remove</a></div></div></li>");
});
console.log('Notes loaded');
} else {
notes.append("<li>There are currently no notes for this contact</li>");
}
});
}
Now the problem:
For some reason this does not update consistently in real time. The data is updated fine on the server side but on the client side the update/refresh does not always update. I might add a note and get a correct update response but the refresh method seems to be receiving the old data and always be one note behind. So the next time I add a note, the one I added before then appears and so forth.
Another problem I am experiencing is the methods seem to stack on each event so if I add one note (or one of the other methods) I will see the console say "notes loaded" but on the second note it says "notes loaded" twice, then on the 3rd note added 3 times and so forth.
I am sure there must be something fatal flaw in the design of my code here but I am not experienced enough with javascript/jquery to notice what direction I am going wrong so I can fix it.
I thought that this was an issue with ajax caching and not refreshing the result so I have adjusted the ajax request as cache none and also to send no cache headers. I am running in wamp.
In your case, your refresh code will always run before your data got updated. Because ajax is asynchronous so the code behind and below ajax will always execute nearly the time your ajax running.
At the time you run your post_data function to call the API, the refresh function got run too. So it's done before your data got updated.
You should run refresh function inside ajax callback. For example:
this.post_data = function(obj,uri, callback)
{
$.ajax({
data: obj,
dataType: 'json',
type: 'post',
url: uri,
headers: { "cache-control": "no-cache" },
cache: false,
success: function (response) {
if (response.success == true)
{
$("#alert_success .msg").html(response.message);
$("#alert_success").fadeIn(200).delay(2000).fadeOut(200);
}
else
{
$("#alert_error .msg").html(response.error);
$("#alert_error").fadeIn(200).delay(2000).fadeOut(200);
console.log(response.error);
}
callback();
}
});
}
And in modal_update, you pass refresh function to post_data as a callback:
this.modal_update = function(data)
{//
// Declare a few variables for the data object we've received
obj = data.obj // The form element to serialize
uri = data.uri;
// Get the form ID from the data-target attribute
id = obj.attr('data-target');
// URL to send to
url = this.site_url + uri + id;
// The form object
this.post_data(obj.serialize(),url, this.refresh);
// Hide Modal
obj.closest('.modal').modal('hide');
}
You should read more about asynchronous ajax. You can use other tricky solution is setTimeout to run this.refresh but I do not recommend that because you not sure when the update is done.

ASP.net: AJAX Result Not Kicking Off

I think this will be a weird one for you as I am at my wits end with this. On a screen I have in a table, I have a link being clicked that is setting off a javascript/ajax request. I have similar code in another screen that works perfectly as it heads down into the success part of the ajax call and runs code in the success portion of the call. For some reason though I can't seem to get this to work and when I debug it in chrome, I lose my breakpoints and it never seems to get into the success portion of the Ajax call.
#section scripts{
<script>
// Get the bond ID Data from the row selected and return that to the program.
function getIDData(el) {
var ID = $(el).closest('tr').children('td:first').text();
var iddata = {
'ID': ID
}
console.log(iddata);
return iddata;
}
// Submit the data to a function in the .cs portion of this razor page.
$('.updatelink').click(function () {
var bondid = JSON.stringify(getIDData(this));
$.ajax({
url: '/Maintenance/Bond_Maint?handler=UpdateandReloadData',
beforeSend: function (xhr) {
xhr.setRequestHeader("XSRF-TOKEN",
$('input:hidden[name="__RequestVerificationToken"]').val());
},
type: 'POST',
dataType: 'json',
data: { bondid: bondid },
success: function (result) {
if (result.pass != undefined) {
document.forms[0].submit();
}
},
});
});
</script>
}
The ASP.net code behind that is calling does an update to the database and then passes back a variable containing Success as its message.
//-------------------------------------------------------------------------------
// Try to get and insert the data from a selected row and copy it
//-------------------------------------------------------------------------------
public ActionResult OnPostUpdateandReloadData(string bondid)
{
return new JsonResult(new { pass = "Success" });
}
I'm not sure how else to describe my issue other than when I debug my other code via the browser, it appears to take a different path than this code does and I cannot fathom why. For reference my other code looks like this:
#section scripts{
<script>
// Get the offender ID Data from the row selected and return that to the program.
function getIDData(el) {
var ID = $(el).closest('tr').children('td:first').text();
var iddata = {
'ID': ID
}
console.log(iddata);
return iddata;
}
// Submit the data to a function in the .cs portion of this razor page.
$('.copybtn').click(function () {
var offenderid = JSON.stringify(getIDData(this));
$.ajax({
url: '/Copy_Old_Account?handler=CopyData',
beforeSend: function (xhr) {
            xhr.setRequestHeader("XSRF-TOKEN",
                $('input:hidden[name="__RequestVerificationToken"]').val());
        },
type: 'POST',
dataType: 'json',
data: { offenderid: offenderid },
success: function (result) {
if (result.path != undefined) {
window.location.replace(result.path);
}
},
});
});
</script>
}
Any help would be appreciated.
Okay guys so first off, thank you everyone for responding to my question. Frank Writte and Alfred pointed me into the right direction by looking for the status in the network tab for my calls. I found out that I was getting cancellations for my requests. After looking into that I found this article What does status=canceled for a resource mean in Chrome Developer Tools? that has an answer from FUCO that gave me what I needed to do. Apparently I needed to add event.preventDefault(); in front of my ajax call and all of a sudden my code worked. I'm not sure I completely understand why this works but I can't complain about the results. Again thank you everyone for trying to help. This one has been boggling my mind all morning.

Proper way of doing AJAX request to retrieve data from database

I got a database with one table in it.
Table has Company and Time columns, and some more, but these two are important.
So the user makes an appointment through the filling of the form.
In the form I have 2 <select>s - Company And Time, so he chooses both from the selections.
He clicks a button and the form is stored in the database.
How do I use AJAX to retrieve all the hours(Time) that are in use, and then disable them accordingly.
For example: I made the appointment selected Nokia from Companies and 9:30 from Time dropdowns. Now You want to make the appointment with Nokia but the 9:30 time is disabled because it has already been used.
What would be the correct way to use AJAX for this:
this is my structure
function MakeApp() {
var AppWith = $("#CompanySelect").val();
var AppTime = $("#TimeSelect").val();
var Yritys = $("#YritysNtext").val();
var Henkilonimi = $("#HenkilonimiText").val();
var Asema = $("#AsemaText").val();
var PuhelinNR = $("#PuhelinText").val();
var EMail = $("#EMailText").val();
var Keskustelun = $("#KeskustelunText").val();
var app = { AppWithYritys: AppWith, AppTime: AppTime, YritysN: Yritys, Henkilonimi: Henkilonimi, Asema: Asema, PuhelinNR: PuhelinNR, EMail: EMail, Keskustelun: Keskustelun }
var request = $.ajax({
type: "POST",
data: JSON.stringify(app),
url: "/api/Appointments",
contentType: "application/json",
dataType: "html"
});
request.done(function (podaci) {
if (podaci != -1) {
alert("You Have successfully made an appointment");
location.assign("BookAppointment.html");
}
else {
$("#p1").html("Greska pri unosu");
}
});
request.fail(function (gr) {
$("#p1").html(gr.statusText);
});
};
Actually it's your server job to manage data and database. AJAX is only a way to send information to a server aysnchronously. What you could do, is when you load the page, you retrieve only the occupied time with AJAX, you disable their options in your select, and whenever your server receive an request, it checks if there is an available place for the company and times.
I'm sorry i don't have a code for your since I think it's pretty clear. If it's not, feel free to comment, i'll try to help you the best i can.
Edit
Here I have a few lines of code, it's not complete since we are missing a few informations but it is the main algorythm.
Your server:
{GET}
public void getUnavailable() {
//get all times from Databases for today's date.,
//Encode them in JSON.
//returns the times.
}
Lets assume that your JSON looks like this:
[
{
"company": "Nokia",
"times": [
"9:30",
"10:00",
"10:30"
]
}
]
You need to retrieve your JSON and parse it to disable the time in the selected select:
$(document).ready(function(){
$.ajax({
'url': API_URL + 'event/getUnavailable',
'method': 'GET',
'success': function(data) {
$.each(data.data, function($index, $company){
var select = /* .. Get the Select of the current company .. */
$.each($company.times, function($index, $times){
select./*.. Find the time associate with $time .. */.setDisable(true); // I don't know if setDisable is the correct function, you might want to check this out.
})
})
},
'error': function(error) {
console.error(error.data);
}
});
$('.myForm').submit(function(){
// This is where you submit your data to your server.
$.ajax({
'url': API_URL + "event/create",
'method': 'POST',
'data': /* your data */,
'success': function(){
console.log('success');
},
'error': function(error) {
console.error(error);
}
})
});
})
This is the most I can do with the info I have.
The real way to handle this, is whatever web technology you have behind /api/Appointments, is to return whatever appointments are available. Your variable names don't make much sense to me, so try to understand what the code below does.
$.get( "/api/Appointments", JSON.stringify(app) )
.done(function( data ) {
//note that the "data" variable holds your returned appointments
//I would return a json document of available appointment times to filter your select
//sample json would look something like this
// { "availableAppointments": ["9:30 AM", "10:00 AM"] }
// and then iterate through available appointments and populate your select
for(var i = 0; i < data.availableAppointments.length; i++){
$('#yourSelectId').append($('<option>', {
value: 930,
text: data.availableAppointments[i]
}));
}
});
Please note this code may not be syntactically correct.
Here are some links that helped me answer this for you, in case they might help.
Adding options to a <select> using jQuery?
https://api.jquery.com/jquery.get/

Is there a time lag in the YouTube Data API 3 rate endpoint?

I have an application that displays a YouTube video and has a rate button to allow a user to like or unlike the video. On the click event 3 functions are called chained together through the success function of the ajax. The flow is this: ytvRate() -> getRating() -> showRating()
When I log the actions and results the response from getRating() does not have the value that I sent in ytvRate(). If I wait a while and refresh the page, the result of getRating() comes back correct. I call getRating() inside the success function of the ajax in ytvRate(). Doesn't that mean the function should not be called until a success response is received?
Here is an example of my logs:
rating sent: like
call get rating
this is my rating: none
call show rating
As you can see, the rating returned from the API is not correct - it should be the rating I just sent. Upon refresh the same call does return the correct rating... so, is there a delay or something to the data api updating the correct information? How can I get the correct rating on the same button click that sends the request?
Here are the functions (showRating does not seem relevant to the problem. It works fine as long as it gets the correct rating - which it is not.)
function ytvRate(id, rating, event){
event.preventDefault()
var apiKey = 'This is a valid key';
var client_id = 'This is a valid client id';
var redirect_uri = 'This is a redirect uri';
var scope = 'https://www.googleapis.com/auth/youtube';
var rateUrl = 'https://www.googleapis.com/youtube/v3/videos/rate?id='+id+'&key='+apiKey+'&rating='+rating;
if(getHash().access_token){
var token = getHash().access_token;
$.ajax({
type: "POST",
url: rateUrl,
beforeSend: function (request){
request.setRequestHeader('Authorization', 'Bearer ' + token);
},
success: function(data){
console.log('rating sent: '+rating);
getRating(id);
},
error: function(e) {
console.log(e);
}
});
} else{
window.location = 'https://accounts.google.com/o/oauth2/v2/auth?client_id='+client_id+'&redirect_uri='+redirect_uri+'&scope='+scope+'&response_type=token&prompt=consent&include_granted_scopes=false';
}
return false;
}
function getRating(id){
var getRatingUrl = 'https://www.googleapis.com/youtube/v3/videos/getRating?id='+id;
console.log('call get rating');
if(getHash().access_token){
var token = getHash().access_token;
$.ajax({
type: "GET",
url: getRatingUrl,
beforeSend: function (request){
request.setRequestHeader('Authorization', 'Bearer ' + token);
},
success: function(data){
var rating = data.items[0].rating;
console.log("this is my rating: " + rating);
showRating(rating, id);
}
});
}
}
function showRating(response, id){
console.log('call show rating');
numLikes(id);
if(response == 'like'){
document.getElementById("notliked").className = "hide";
document.getElementById("liked").className = "";
document.getElementById("like-btn").style.color = "#87CEFA";
document.getElementById("like-btn").setAttribute("onclick", "ytvRate('"+id+"', 'none', event)");
} else{
document.getElementById("notliked").className = "";
document.getElementById("liked").className = "hide";
document.getElementById("like-btn").style.color = "inherit";
document.getElementById("like-btn").setAttribute("onclick", "ytvRate('"+id+"', 'like', event)");
}
}
Edit:
Interestingly, if I call the youtube/v3/videos resource in a new method instead of youtube/v3/videos/getRating and access the statistics.likeCount, the number is instantly updated. Why can I not receive the user rating with the same efficiency?
After the discussion in the comments I suggest you to take a different approach. When ytvRate success you don't need to fetch getRating as you already know what is the rating set by the user.
The rate method is like a setter in regular programming language - if it successed (didn't throw an exception or returned an error) you can assume the current value is the one you set without fetching it again. This might be wrong assumption in multithreaded/distributed enviroments but might be ok in your case.
function ytvRate(id, rating, event){
...
success: function(data){
console.log('rating sent: '+rating);
showRating(rating, id);
}
...
}

Categories

Resources