Looking for some advice on whether my syntax is correct for this Prototype to jQuery conversion.
I have both frameworks loading at the same time and would like to convert all scripts to jQuery to reduce page load weight and speed.
Prototype
Looking to replicate this in jQuery:
if (snapshots.items.length < snapshots.total_entries) {
new Ajax.Request(snapshots.url, {
method: 'GET',
parameters: {
page: snapshots.current_page + 1,
per_page: snapshots.per_page
},
onSuccess: function(response) {
var start = snapshots.items.length;
snapshots.items = snapshots.items.concat(eval(response.responseText));
for (i = start; i < snapshots.items.length; i++) {
$('snapshots').appendChild(render_snapshot(snapshots.items[i].snapshot));
Photo.Carousels.instances[Photo.Filmstrip.carouselIndex].slides.push($('slide_' + snapshots.items[i].snapshot.id));
Photo.Carousels.instances[Photo.Filmstrip.carouselIndex].slides[i]._index = i;
}
snapshots.current_page++;
Photo.Filmstrip.currentSnapshot(currentSnapshot);
}
});
}
to jQuery
if (snapshots.items.length < snapshots.total_entries) {
$j.ajax({
url: snapshots.url,
data: {
page: snapshots.current_page + 1,
per_page: snapshots.per_page
},
success: function (response) {
var start = snapshots.items.length;
snapshots.items = snapshots.items.concat(eval(response.responseText));
for (i = start; i < snapshots.items.length; i++) {
$j('.snapshots').append(render_snapshot(snapshots.items[i].snapshot));
Photo.Carousels.instances[Photo.Filmstrip.carouselIndex].slides.push($j('slide_' + snapshots.items[i].snapshot.id));
Photo.Carousels.instances[Photo.Filmstrip.carouselIndex].slides[i]._index = i;
}
snapshots.current_page++;
Photo.Filmstrip.currentSnapshot(currentSnapshot);
}
});
}
Yes, this looks right - I know jQuery much better than Prototype, so I'm guessing a little, but it makes sense (assuming you've used $.noConflict to assign jQuery to $j). The only issue here, as #Greg pointed out in his comment, is the eval - I assume you're returning JSON data, so if you include the config option:
dataType: 'json'
jQuery will parse this automatically, in a way that's safer than a plain eval. In fact, I'm pretty sure that in most cases if you leave this option out, jQuery will sniff your response body and guess intelligently whether to parse it as JSON, XML, HTML, script, or text, in which case your eval would be unnecessary.
Related
I created a site which load every few seconds data from multiple sources via AJAX. However I experience some strange behavior. Here is the code:
function worker1() {
var currentUrl = 'aaa.php?var=1';
$.ajax({
cache: false,
url: currentUrl,
success: function(data) {
alert(data)
},
complete: function() {
setTimeout(worker1, 2000);
}
});
}
function worker2() {
var currentUrl = 'aaa.php?var=2';
$.ajax({
cache: false,
url: currentUrl,
success: function(data) {
alert(data)
},
complete: function() {
setTimeout(worker2, 2000);
}
});
}
The problem is that many times, one of the workers returns NaN. If I change the frequency of calls for, lets say, 2000 and 1900, then everything is working ok and I got almost no NaN results. When those frequencies are same, I get over 80% NaN results for one of the calls. It seems like the browser cannot handle two requests called at exact same time. I use only those two workers, so the browser shouldn't be overloaded by AJAX requests. Where is the problem?
Note that the aaa.php works with the mySql database and do some simple queries base on parameters in url.
All you need is $.each and the two parameter form of $.ajax
var urls = ['/url/one','/url/two', ....];
$.each(urls, function(i,u){
$.ajax(u,
{ type: 'POST',
data: {
answer_service: answer,
expertise_service: expertise,
email_service: email,
},
success: function (data) {
$(".anydivclass").text(data);
}
}
);
});
Note: The messages generated by the success callback will overwrite
each other as shown. You'll probably want to use
$('#divid').append() or similar in the success function.
Maybe, don't use these workers and use promises instead like below? Can't say anything about the errors being returned though without looking at the server code. Below is working code for what it looks like you are trying to do.
This is a simple example but you could use different resolvers for each url with an object ({url:resolverFunc}) and then iterate using Object.keys.
var urls = [
'http://jsonplaceholder.typicode.com/users/1',
'http://jsonplaceholder.typicode.com/users/2',
'http://jsonplaceholder.typicode.com/users/3',
'http://jsonplaceholder.typicode.com/users/4',
'http://jsonplaceholder.typicode.com/users/5',
'http://jsonplaceholder.typicode.com/users/6',
'http://jsonplaceholder.typicode.com/users/7'
]
function multiGet(arr) {
var promises = [];
for (var i = 0, len = arr.length; i < len; i++) {
promises.push($.get(arr[i])
.then(function(res) {
// Do something with each response
console.log(res);
})
);
}
return $.when(promises);
}
multiGet(urls);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
I am looking to send a number of different queries via $.ajax as JSON.
I have stored these queries in an object using the following:
var objectName = {
"name1": {
"queryName": "longname1",
"queryAction": "JSONtoSend"
},
"name2": {
"queryName": "longname2",
"queryAction": "JSONtoSend"
},
};
I am then going through the queryActions and setting them:
for (var i = 0, len = Object.keys(objectName).length; i < len; ++i) {
var indexName = Object.keys(objectName)[i];
objectName[indexName].queryAction = "";
var JSONtoTransfer = objectName[indexName].queryAction;
}
$.ajax({
type: "POST",
url: 'URL',
data: JSONtoTransfer,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(dataReturn){
alert(dataReturn.blah);
}
});
I am unable to set the var JSONtoTransfer. It gives me an unexpected [ error. How do I get around this? I get the same error if I enter it straight into the data parameter of $.ajax.
The code I am using is storing the queries in the object correctly, but I need a way to iterate through them all and send via $.ajax.
Thank you for the help. This code is probably not the most efficient way of doing things, so if anyone has any advice, it's more than welcome too :-)
So I wrote the original code wrong, the $.ajax call should be included in the for statement. So it actually iterates....
Anyway, what I found to work was creating an array, pushing the queryAction into it and then stringifying it...
Few problems:
JSONtoTransfer is out of scope of your ajax call. If you want to populate JSONtoTransfer on every iteration and make an ajax request with this different value each time - put the ajax call inside the for loop (although I would seriously consider refactoring this so that you make one ajax call, and deserialize it differently (if it's your server-side code handling it))
You're setting objectName[indexName].queryAction to an empty string, then assigning this value to JSONtoTransfer (now always going to be an empty string)
You have your for syntax a bit muddled up. Best practice would be to change
for (var i = 0, len = Object.keys(objectName).length; i < len; ++i) {
to
for (var i = 0; i < Object.keys(objectName).length; ++i) {
i.e. there's no need to keep initialising len to the same value. NOTE: This is more for readability, not (so much) performance. If you had another use for len inside the loop this advice wouldn't apply.
Your variable objectName is in fact JSON data already. I might be wrong but I think this should work (with less code):
var jsonData = {
"name1": {
"queryName": "longname1",
"queryAction": "JSONtoSend"
},
"name2": {
"queryName": "longname2",
"queryAction": "JSONtoSend"
},
};
//Post with AJAX
$.post('url.php', jsonData, 'json')
.done(function(data) {
alert('Succes!')
})
.fail(function(data) {
alert('Failed!')
});
//This does the same (Post with AJAX)
$.ajax({
url: 'url.php', //Get action attribute of the form
type: "POST",
data: jsonData,
dataType: "json",
.done(function() { //or success: function() {
alert( "success" );
})
.fail(function() { //or error: function() {
alert( "error" );
})
.always(function() { //or beforeSend: function() {
alert( "complete" );
});
});
I am not sure what you want but as pointed out by others there are many issues with your code, but i think you want to execute ajax call one after the other iteratively. if that is what you want then take a look at jQuery deffered -docs are here.Hope that helps
I am getting different errors in FF, Chrome and IE, but it all boils down there is an error with the data in $.ajax. Following is the code. Please go easy if I made a dumb mistake. I have spent hours researching this and can't figure it out. Any help appreciated.
Edited to include the error messages
FF Error message: NS_ERROR_XPC_BAD_CONVERT_JS: Could not convert JavaScript argument
Chrome Error message:Uncaught TypeError: Illegal invocation
IE9 Error message: SCRIPT65535: Argument not optional
Here is the code
mc.mc_data.click_tracking = [];
var sequence = 0;
var send_it;
// the container click event will record even extraneous clicks. need to change it to extending the jquery on click handler
$('#container').on('click', function(event) {
logClicks(event);
if(!send_it){
sendIt()
}
sequence++;
});
function sendIt(){
var tracking = mc.mc_data.click_tracking;
var url = '/ajax/click_trackin';
console.log("clicks["+sequence+"] "+$.isArray(tracking));
$.each(tracking, function(i,v){
console.log(i + v.innerText + " - " + v.sequence);
});
send_it = window.setInterval(function(){
$.ajax({
type: 'POST',
url: url,
data: {
clicks:tracking
},
success: function(response)
{
if(response.result.length<1){
console.log(response+ ': no response');
}else{
console.log(response);
tracking = mc.mc_data.click_tracks = [];
}
mc.mc_data.click_tracks = [];
clearInterval(send_it);
sendIt();
},
error: function(a, b, c){
console.log(a+" - " + b+" - "+ c);
clearInterval(send_it);
}
});
}, 5000);
}
//
function logClicks(e){
var temp_click = {
'business_id':window.mc.businessid,
'userid':window.mc.userid,
'timestamp':e.timeStamp,
'leg':window.mc.currentLeg,
'workflow': 'dummy data',
'sequence': sequence,
'type':e.type,
'target':e.target,
'parent': e.target.parentElement,
'id':e.target.id,
'class':e.className,
'innerText': $(e.target).text()
}
mc.mc_data.click_tracking.push(temp_click);
}
For data, you are meant to pass an object which will later be converted into a query string. You are passing the variable tracking, which contains stuff like e.target.parentElement, which is a DOM Node, containing really a lot of further properties (like other DOM Nodes!). The error can originate from either having problems converting a DOM Node into a query string, or creating a way too long query string. It would not make much sense to send a DOM Node to the server anyways.
Only send what is necessary and can be reasonably converted to a query string.
I have some ajax calls in multiple JavaScript functions. Each one does a post / get to a functions.php file
The functions.php has multiple functions that should correspond with the ones from JavaScript.
For example in js I have:
function one() {
$.ajax({
type: 'POST',
url: 'http://www.example.com/functions.php',
data: vals,
dataType:'json',
success: function (data) {
alert(data);
}
});
}
function two() {
$.ajax({
type: 'POST',
url: 'http://www.example.com/functions.php',
data: othervals,
dataType:'json',
success: function (data) {
alert(data);
}
});
}
function three() {
$.ajax({
type: 'GET',
url: 'http://www.example.com/functions.php',
data: { get_param: 'user' },
dataType:'json',
success: function (data) {
alert(data);
}
});
}
In PHP I have something like this:
if (isset($_POST['city'])) { // this comes from the javascript vals json object
$city = $_POST['city'];
function one() {
// do something
return true;
}
}
function two() {
// do something
return true;
}
if (isset($_GET['get_param']) && $_GET['get_param'] == 'user'){
function three() {
// do something
return true;
}
}
Maybe the PHP side is a bit confusing the way I write it, but in the end I want the function one to only deal with the corespondent function from the PHP file. Obviously they don't need to have the same name.
The PHP functions can return true or false or 1 or 0, and that suppose to be the alerted data alert(data);.
If there is more confusion on what I want please let me know and I'll clarify.
Why not split the PHP functions in separate smaller scripts? They stand for different endpoints in your application and cannot be called together, so they should not be together.
Have you checked out a REST library style. It looks like your doing basically that but a bit more confusing. When i say REST library i do not mean a purely RESTful library, but instead each function in your back-end is navigable via url.
The way your doing it is fine (as long as the functions data does not depend on any other function data (as it could lead to some funny results)). Its just a lot easier to do more of a restful approach. Its fairly simple to set up a rest library.
I just find that doing the whole $_POST[...] and then keep doing it is just cumbersome over time and becomes harder and harder to manage, because there is always some new twist on what is needed then you end up with 100's of methods for taking care of calling back end functions.
MyApi = {
/**
* The API Version
*/
API_VERSION: "0.5",
SITE_URL: "http//myurl.com/",
/**
* The API URL
*/
apiURL: function(tokens) {
return MyApi.SITE_URL + MyApi.API_VERSION + "/api/" + MyApi.apiTokenizer(tokens);
},
/**
* The tokenizer for the API.
*/
apiTokenizer: function(tokens) {
var str = '';
$.each(tokens, function(key, value) {
str += value + "/";
})
return str;
}
}
Thats the javascript for producing new api links, then you could have something like
function callBackend(tokens) {
$.ajax({
type: 'POST',
url: MyLibrary.apiURL(tokens),
dataType:'json',
success: function (data) {
alert(data);
}
});
}
On your backend you would need an .htaccess file like so
RewriteRule 0\.5/(.*) api/_MyApi.php?v=0\.5&state=$1 [QSA]
Then you could write a back end switch statement that would take apart the state (delimiters would be "/") that would navigate you to the end time library call.
<?php
$state = MyParser::Parse($_REQUEST["state"]);
$output = array();
switch ($state) {
case "case1":
//do stuff
break;
}
echo json_encode($output);
?>
That way output is always handled the same way.
Just as a note. That was a very VERY simple and INCOMPLETE implementation, but i find that its a lot easier to maintain than a $_POST that goes to 1 of 100 different files that all have very similar output and all of that.
Cheers! Happy coding
I have JavaScript using jQuery and AJAX which creates a dynamic array, which has some values used for AJAX request as below;
<script type="text/javascript">
var array = Array("y","y","x","y","y","y");
function updateBackground(cellId, titleId) {
var i = 0;
$.ajax({
type: "POST",
url: "ajax.php",
data: {
filename: Array(array[i], "testdata", $("#"+titleId).html())
},
success: function(response){
$("#"+cellId).css("background-image", "url('pdfthumb/" + response + "')");
}
});
i++;
}
</script>
The script is suppose to submit values in the array in array[i] for each AJAX request. I made a variable var i which auto increments.. But the script is not working.. The script works well if array[i] is replaced by array[0] or array[1] etc..
How can I solve the syntax error?
Every time you call updateBackground() i = 0 (again). May be you must initialize i outside of the function.
What happens if i > array.length? And I would rename the variable.
You don't have an iterator. Your variable i gets set to 0 every time the function runs. The increment at the end is useless.
Maybe you need something like this?
var array = Array("y","y","x","y","y","y");
function updateBackground(cellId, titleId) {
for( var i = 0; i < array.length; i++ ) {
$.ajax({
type: "POST",
url: "ajax.php",
data: {
filename: Array(array[i], "<?php echo $dir; ?>", $("#"+titleId).html())
},
success: function(response){
$("#"+cellId).css("background-image", "url('pdfthumb/" + response + "')");
}
});
}
}
Each time you call updateBackground() function, the i variable is being reinitialized. It's just a local variable and as soon as the function finishes it's being destroyed by GC. You could do something like this:
var UpdateBackground = {
array: [..],
counter: 0,
doUpdate: function(cellId, titleId) {
// AJAX request
this.counter++;
}
};
UpdateBackground.doUpdate(1, 1);
UpdateBackground.doUpdate(1, 1);
I think that you should send the whole array maybe as a commaseparated string and instead and make just one ajax request, because http-requests are expensive and change the server side code accordingly. And fetch the cellids as an array.
If you think that you have a long list or a table it can be like a lot of requests. Do the stuff in client code and do the stuff in server code and keep the number of http-requests as few as possible.
And use the join method on the array.
var arr = [ 'y', 'y' ];
arr.join(',');
// outputs y, y
I fixed it... Thank you so much #Jed, #Pointy, #Crozin, and #Lord Vader for helping me to figure it out.... :)
I just take var i = 0; outside the loop.... above var array like;
var i = 0;
var array = Array("y","y","x","y","y","x");