I work on a Backbone app with a collection for data sources. Whenever a new data source is added, its model is added to the collection, and a jQuery Ajax call is made for it like this:
fetch: function() {
var model = this,
url = model.get("url");
function testCallback(parObj) {
return function(data, textStatus, jqXHR) {
alert("test - "+parObj.url+" : "+data.sourceurl);
}
}
$.ajax({
url: url,
type: "GET",
dataType: "jsonp",
jsonpCallback: "data",
success: testCallback({ model: model, url: url })
})
.done(function (data) {
alert("done - "+model.get("url")+" : "+data.sourceurl);
});
}
The fetch() is called in rapid succession, and debugging it I can see everything is ok when I initiate the Ajax request.
Everything works great if I only add two data sources.
But both the done() and testCallBack() functions mixes up the data when I have three requests running simultaneously on three different domains (same happens in both Chrome and Safari).
For instance:
URL 1 gets the data from URL 1.
URL 2 gets the data from URL 3.
URL 3 gets the data from URL 2.
Am I doing something wrong? Any help is greatly appreciated.
That's because you're setting the jsonpCallback parameter to the same thing for each request. Just remove that line entirely as jQuery will automatically create unique ones for you.
Related
Issue:
The first ajax is working properly in the main.js, the second one is doing its job at first look but I think there might be a bug somewhere. I can reach the getProducts method after I click to the button.
The product_list.html file should appear on the browser screen, but it doesn't.
I get no error message on the front-end or the back-end.
This is what I noticed: After click to the button -> F12 -> Network -> products -> I can see here a status code: 200 and the product_list.html file content as response.
In case the POST ajax call succeeds and in the case I add: location.href = "/products";, the browser will load product_list.html
I use the get ajax call because i need to pass the jwt token in the req header. (I deleted the jwt authentication parts from the code below because I narrowed down the error to the $.ajax() and res.sendFile() relationship)
//routes.js
routes.get("/products", ProductController.getProducts);
//ProductController.js
var root = path.join(__dirname, '../../views');
module.exports = {
getProducts(req, res){
console.log("getProducts!"); //I can see in the console
res.sendFile("product_list.html", {root}) //It doesn't render the html
},
}
//main.js
$("#btn-login").click(function(){
$.ajax({
type: 'POST',
url: "http://localhost:8000/login",
dataType: "json",
contentType: "application/json",
data: JSON.stringify({
"username": $("#login-user").val(),
"password": $("#login-pwd").val(),
}),
success: function(data){
if ($("#login-chkbx").is(':checked')){
$.ajax({
url: "http://localhost:8000/products",
type: 'GET',
beforeSend: function (xhr) {
xhr.setRequestHeader("user", localStorage.getItem("user"));
},
});
}
}else{
console.log("Checkbox is not checked");
}
}
});
});
What causes the issue and how to solve it?
Thanks!
file should appear on the browser screen
No it does not and it should not. The file should be returned to the ajax function call in the success callback:
$.ajax({
url: "http://localhost:8000/products",
type: 'GET',
beforeSend: function (xhr) {
xhr.setRequestHeader("user", localStorage.getItem("user"));
},
success: function (file) {
// The file is in the "file" variable above.
// Do whatever you want with it. For example you can replace
// the current page with the returned file:
document.body.innerHTML = file;
}
});
That is the whole point of AJAX - a mechanism for programmers to override the normal flow of HTTP requests that loads the response to the browser page. If it allows you to not load the response to the browser page it also means it will not automatically load the response to the browser page - because doing so will not allow you to not load the response.
If you want to automatically load the response then don't use ajax:
// Replace $.ajax(... with:
window.location.href = "http://localhost:8000/products";
However, this method does not allow you to set custom request header.
in your frontend code you do nothing with the GET /products response
the backend sendfile as the name says it just sends the file over to the requester. Being an ajax call, it must be rendered by the frontend code.
Add something like success: response => $('body').html(response)
I use ajax in Arcgis Javascript (if you are familiar, i just inform you that i use it, never mind) to select some data and show it in modal window, but i have problem, e.g. i clicked several feature on map (e.g. 3 features) and on each click i get different info, but if i click info button again and again it shows these selected features one by one even though i have selected different feature on map, it stores data and does not show correct info when i continue click and get info from a map.
I use 'cache: false' in $.ajax but it's not working.
Any help please, i checked this article, but it didn't help.
here is a piece of code i use
$(document).on('click', '#vf', function () //
{
var folder_name = 'inv_images/' + graphic.attributes.Wis_invent_N;
var action = "fetch_files";
$.ajax({
url: "action.php",
method: "POST",
data:{
action:action, folder_name:folder_name,
},
cache: false,
success: function(data)
{
$('#file_list').html(data);
$('#filelistModal').modal('show');
}
})
});
});
If it's the browser that's caching the ajax request (ex. IE does that) then you can change the actual request that's done by adding a timestamp to the url:
...
$.ajax({
url: "action.php?t=" + new Date().getTime(),
...
The backend should ignore the extra t parameter, but your browser thinks it's a different url therefore doesn't use the cached response.
I am building a web app that displays data about flowers that is stored in my local server running bottle.
My front end is html, js with ajax;
My back end is python with bottle
In the browser there is an empty div in which the data is to be displayed.
Below it there is a row of images. When the user clicks on an image the data should display in the div above.
I tried using $.ajax instead of $.get, and I'm getting the same result.
This is my event listener in js:
$('.image').click((e)=>{
$('.selected').removeClass('selected');
$(e.target).addClass('selected'); // just a visual indication
$.get('/flowerdesc/'+$(e.target).attr('id')).done((data)=>{
flowerInfo = JSON.parse(data);
$('#flower-title').empty();
$('#flower-title').html(flowerInfo.name);
$('.desc-text').empty();
$('.desc-text').html(flowerInfo.description);
})
})
This is my handler for this request:
#get('/flowerdesc/<flower>')
def get_flower_desc(flower):
return json.dumps(data[data.index(filter(lambda f: f.name == flower, data)[0])])
(data is an array of dictionaries, each containing data of a single flower)
I am getting a 404 error (the function get_flower_desc is not executed at all) that possibly is happening because of the argument, because whenever I use a a function with no parameters and pass in no arguments I am getting the result that I'm expecting.
I found that I had to formulate an AJAX request quite precisely to get it to work well with Bottle in a similar scenario.
Here is an example with a GET request. You could attach this function to the event handler or move it directly to the event handler.
function getFlowerData(id) {
$.ajax({
type: "GET",
cache: false,
url: "/flowerdesc/" + id,
dataType: "json", // This is the expected return type of the data from Bottle
success: function(data, status, xhr) {
$('#flower-title').html(data['name']);
$('.desc-text').html(data['description']);
},
error: function(xhr, status, error) {
alert(error);
}
});
};
However, I found better results using a POST request from AJAX instead.
function getFlowerData(id) {
$.ajax({
type: "POST",
cache: false,
url: "/flowerdesc",
data: JSON.stringify({
"id": id,
}),
contentType: "application/json",
dataType: "json",
success: function(data, status, xhr){
$('#flower-title').html(data['name']);
$('.desc-text').html(data['description']);
},
error: function(xhr, status, error) {
alert(error);
}
});
};
For the POST request, the backend in Bottle should look like this.
#post("/flowerdesc") # Note URL component not needed as it is a POST request
def getFlowerData():
id = request.json["id"]
# You database code using id variable
return your_data # JSON
Make sure your data is valid JSON and that the database code you have is working correctly.
These solutions using AJAX with Bottle worked well for me.
I want to know the content type of a given url input by the user inside my Javascript code. Actually, I have a drop-down list (html,csv,xls etc.) and I want to make it so when the user inputs an url, I want to detect the type of the content of the url and based on this type I want to set the value of my drop-down list (html,csv,xls etc.). I know, I can get the content type using Ruby like this :
require 'open-uri'
str = open('http://example.com')
str.content_type #=> "text/html"
or, also, I could use curl to get the content and then parse it to know the content type. But, I need to do this inside my Javascript code because of my need explained above. Any thought ?
EDIT_1 :
I tried this code in my javascript :
$("#wiki_form_url").change(function(){
$.ajax({
type: "GET",
url: "content.rb",
data: {
// input_url: $("#wiki_form_url").val()
},
dataType: "html"
}).done(function (data) {
// `data` contains the content-type
alert('Success !!!');
}).fail(function () {
alert("failed AJAX call");
});
});
I have a ruby script content.rb inside which I do :
require 'open-uri'
str = open('http://www.ofdp.org/benchmark_indices/25')
str.content_type
But, it does not seem to work. I am getting Ajax failure. May be it's because of url path of the script content.rb ? How should I specify a script path here ? (Relative or absolute)
The same origin policy prevents you from using client side JavaScript to directly discover information about arbitrary URIs (URIs you control are a different story).
You'll need to get that information with another technology, such as your server side Ruby.
You could do this by simply submitting a form to the server and returning a new webpage to the browser.
If you don't want to leave the page, then you can pass the data using Ajax. There are no shortage of Ajax tutorials out there, here is a good one from MDN.
Here's an example of an AJAX call:
$(document).ready(function () {
$("#button_check").on("click", function () {
$.ajax({
type: "GET",
url: "Your URL",
data: {
input_url: $("#textbox_id").val()
},
dataType: "html"
}).done(function (data) {
// `data` contains the content-type
alert(data);
}).fail(function () {
alert("failed AJAX call");
});
});
});
Where your HTML is something like:
<input type="text" id="textbox_id" />
<input type="button" id="button_check" value="Submit" />
And your Ruby code would be something like:
require 'open-uri'
class TestController < ApplicationController
def index
req = open(params[:input_url])
render :text => req.content_type
end
end
I have never used RoR before, so I have no idea if this is right or works in the slightest. But it's what I could quickly conjure up when scrambling through several tutorials. It's simply the concept you seem to be looking for. You'll need to figure out how to map a URL to this method, and then update the AJAX option url to use that.
So in the Javascript code - in the done method, that means the whole AJAX request was successful and the data variable should contain the result from the Ruby code req.content_type.
Atlast I could figure out the whole thing with the great help of #Ian. Here is my completed code : In javascript file :
$("#wiki_form_url").change(function () {
$.ajax({
type: "GET",
url: "/wiki_forms/content",
data: {
input_url: $("#wiki_form_url").val()
},
dataType: "text"
}).done(function (data) {
// `data` contains the content-type
alert('Success');
console.log(data);
// alert(data);
}).fail(function () {
alert("failed AJAX call");
});
});
Inside my wiki_forms controller I created a new method named content :
def content
req = open(params[:input_url])
render :text => req.content_type
end
Then added a new route in routes.rb file :
get "/wiki_forms/content" => 'wiki_forms#content'
and used /wiki_forms/content as the ajax request url. And, everything is working nicely now.
I am having trouble getting a success: function(){} working - the ajax code I am using is this:
jQuery.ajax({
url: 'http://127.0.1/process_form.php'+data,
data: data,
dataType: "jsonp",
jsonp : "callback",
jsonpCallback: "jsonpcallback"
});
data is a simple string and is being passed by jsonp as when complete will pass data cross domains. I know about security with a GET and that Curl would be better, but this is a simple "predefined" string with no user input. The data is just the text from one of 4 links. i.e. "yes" "No" "Don't know" "made this one up" There is actually no need for a form either.
I get all the "data" into the DB but what I can't get to happen is the "next" bit based on the success. If I do a simple success: function(){} nothing happens (with that function) regardless of "what" e.g. an alert etc.
What should (and does of sorts) happen is the data is posted to the DB, a jQuery.getJSON statement then queries the DB and prints out ALL the data i.e. all entered rows, not just the last.
When I say "sort of works" the jQuery.getJSON returns the data, but sometimes "misses" doing it until the next time data is sent. It seems to me all to do with timing because if I wrap the "print" function inside a setInterval() the whole thing works fine. Just I don't really need the setInterval to contunually work.
For example:
jQuery('.addinput').live('click',function(){
var fldID = new Date().getTime();
var fldType = jQuery(this).html().toLowerCase();
var data ='';
data += '?fldID='+fldID;
data += '&fldType='+fldType;
data += iptime;
jQuery.ajax({
url: 'http://127.0.1/process_form.php'+data,
data: data,
dataType: "jsonp",
jsonp : "callback",
jsonpCallback: "jsonpcallback"
});
jQuery('.loader').fadeIn('slow');
setInterval(function() { fn_form(iptime); }, 3000 );
jQuery('.loader').fadeOut('slow');
return true;
});
This works OK but I really don't want the fn_form(iptime) function to be continually refreshed.
What I'd rather see is something like this:
jQuery('.addinput').live('click',function(){
var fldID = new Date().getTime();
var fldType = jQuery(this).html().toLowerCase();
var data ='';
data += '?fldID='+fldID;
data += '&fldType='+fldType;
data += iptime;
jQuery.ajax({
url: 'http://127.0.1/process_form.php'+data,
data: data,
dataType: "jsonp",
jsonp : "callback",
jsonpCallback: "jsonpcallback",
success: function(){
// run fn_form(iptime)
}
});
You can use this alternative solution to jQuery's implementation of JSONP which simplify JSONP calls.
jQuery-JSONP features:
1- error recovery in case of network failure or ill-formed JSON responses,
2- precise control over callback naming and how it is transmitted in the URL,
3- multiple requests with the same callback name running concurrently,
4- two caching mechanisms (browser-based and page based),
5- the possibility to manually abort the request just like any other AJAX request,
a timeout mechanism.