Is there a more efficient way to write the following? I need to loop through objList and pass the UnqKey to wfrmPrint. On success of that I then have to loop though the Pages. I am looping through the pages and unqkeys by passing a integer and checking to see if it is less than the length. I tried to use .when.apply taken from http://www.tentonaxe.com/index.cfm/2011/9/22/Using-jQuerywhen-with-a-dynamic-number-of-objects, but it was loading the unqkeys and then the pages.
//sample objList
[
{
"UnqKey": 1,
"Pages": [
"wfrmSet1Page1.aspx",
"wfrmSet1Page2.aspx"
]
},
{
"UnqKey": 2,
"Pages": [
"wfrmSet2Page1.aspx",
"wfrmSet2Page2.aspx",
"wfrmSet3Page2.aspx",
"wfrmSet4Page2.aspx"
]
}
]
function Loop(iListIndex) {
var obj = objList[iListIndex];
if (iListIndex < objList.length) {
jQuery.ajax({
type: "GET",
url: 'wfrmPRINT.aspx?action=LoadSession&UnqKey=' + obj.UnqKey, //load session that is used in wfrmSet1Pages.. or wfrmSet2Pages..
success: function () {
AddPages(obj, iListIndex, 0);
}
})
} else {
alert('Done');
}
}
function AddPages(obj, iListIndex, iPageIndex) {
if (iPageIndex < obj.Pages.length) {
jQuery.ajax({
type: "GET",
url: obj.Pages[iPageIndex] + '?Print=1', //load html
async: true,
success: function (html) {
iPageIndex++
AddPages(obj, iListIndex, iPageIndex);
},
error: function () {
alert('Failed!');
iPageIndex++
AddPages(obj, iListIndex, iPageIndex);
}
});
} else {
iListIndex++
Loop(iListIndex);
}
}
You might be able to do something like this,
function getData(arr,arrindex) {
$.ajax({
type: "GET",
url: 'wfrmPRINT.aspx?action=LoadSession&UnqKey=' + arr[arrindex].UnqKey
}).then(function(data){
var deferredObj = $.Deferred(), defArr = $.map(arr[arrindex].Pages,function(page){
return $.ajax({type: "GET", url: page + '?Print=1'});
});
$.when.apply(null,defArr).done(deferredObj.resolveWith).fail(deferredObj.resolveWith);
return deferredObj.promise();
}).done(function(){
arrindex++;
if (arr[arrindex]) {
getData(arr,arrindex);
}
else {
alert("done!");
}
}).fail(function(){
alert("FAIL!");
});
}
getData(objList,0);
It gets each wfrm sequentially, and when each one finishes, requests all of the pages for that one at once. Somewhat of a combination between your loop and a deferred $.when
Edit: fixed $.map argument order
Related
I wrote this code for like and dislike for my posts in my blog:
$(".p_like").each(function() {
$(this).click(function() {
ids = $(this).find(".pl_id").val();
t = $(this);
if ($(this).find(".bi").hasClass("bi-heart-o")) {
gfd = 'p';
$(this).find(".bi").addClass("bi-heart");
$(this).find(".bi").removeClass("bi-heart-o");
} else {
gfd = 'm';
$(this).find(".bi").addClass("bi-heart-o");
$(this).find(".bi").removeClass("bi-heart");
}
$.ajax({
type: "POST",
url: "likes.php",
data: {
ids: ids,
k: gfd
},
cache: false,
success: function(result) {
t.find(".nol").html(result);
}
});
});
});
And when I use the code, in some of the post it likes the post and then dislike it.
What is the problem of the code and how can I fix it?
use this :
$(".p_like").find(".bi").click(function(){
ids = $(this).siblings(".pl_id").val();
t = $(this);
if($(this).hasClass("bi-heart-o")){
gfd='p';
$(this).addClass("bi-heart");
$(this).removeClass("bi-heart-o");
}else{
gfd='m';
$(this).addClass("bi-heart-o");
$(this).removeClass("bi-heart");
}
$.ajax({
type: "POST",
url: "likes.php",
data: {ids:ids,k:gfd},
cache: false,
success: function (result) {
t.siblings(".nol").html(result);
}
});
});
and you maybe used this file two time!
Jquery by default query all given selectors ( here .p_like ). It's not needed to iterate over them explicitly.
Jquery methods are chanable. after you select one element you could call methods one after another: $element.addClass(...).removeClass().css(...)
Also you've leaked three variables: ids, t, gfd. maybe they're got overriten before you send em out to server so declare them to make em private to your event handler function.
$('.p_like').click(function() {
var $t = $(this),
$bi = $t.find('.bi'),
$nol = $t.find('.nol'),
ids = $t.find('.pl_id').val(),
gfd;
if ( $bi.hasClass('bi-heart-o') ) {
gfd = 'p';
$bi.addClass('bi-heart').removeClass('bi-heart-o');
} else {
gfd = 'm';
$bi.addClass('bi-heart-o').removeClass('bi-heart');
}
$.ajax({
type: 'POST',
url: 'likes.php',
data: {
ids: ids,
k: gfd
},
cache: false,
success: function(result) {
$nol.html(result);
}
});
});
I have this function
function display() {
$.ajax({
url: "new.php",
type: "POST",
data: {
textval: $("#hil").val(),
},
success: function(data) {
$('.daily').html(data);
}
});
}
and it serves its purpose, the only problem is, a user can click on for as many times as possible, and it will send just as many requests to new.php.
What I want is to restrict this to just 1 click and maybe till the next page refresh or cache clear.
Simple example would be :
<script>
var exec=true;
function display() {
if(exec){
alert("test");
exec=false;
}
}
</script>
<button onclick="javascript:display();">Click</button>
In your case it would be :
var exec=true;
function display() {
if(exec){
$.ajax({
url: "new.php",
type: "POST",
data: {
textval: $("#hil").val(),
},
success: function(data) {
$('.daily').html(data);
exec=false;
}
});
}
}
This should do what you want:
Set a global var, that stores if the function already was called/executed.
onceClicked=false;
function display() {
if(!onceClicked) {
onceClicked=true;
$.ajax({
url: "new.php",
type: "POST",
data: {
textval: $("#hil").val(),
},
success: function(data) {
$('.daily').html(data);
}
});
}
}
During onclick, set a boolean flag to true to indicate that user clicked the link before invoking the display() function. Inside the display() function, check the boolean flag and continue only if it is true. Reset the flag to false after the AJAX completed processing (successful or failed).
You can use Lock variable like below.
var lock = false;
function display() {
if (lock == true) {
return;
}
lock = true;
$.ajax({
url: "new.php",
type: "POST",
data: {
textval: $("#hil").val(),
},
success: function (data) {
$('.daily').html(data);
lock = false;
}
});
}
you can implement this with that way too
$(function() {
$('#link').one('click', function() {
alert('your execution one occured');
$(this).removeAttr('onclick');
$(this).removeAttr('href');
});
});
function display(){
alert('your execution two occured');
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a href="#" onclick="display();" id='link'>Have you only one chance</a>
I have a function in JS & jQuery that fires an AJAX call and it has a callback block to let me know when it's finished:
function ajaxCall(url, type, dataType, dataToSend, callback) {
if (dataType == undefined) dataType = "json";
if (dataToSend == undefined) dataToSend = null;
$.ajax({
url: url,
type: type,
dataType: dataType,
contentType: "application/json",
data: dataToSend,
async: true,
success: function (result) {
callback(result);
},
error: function (data, status) {
console.error("Server Error: " + status);
}
});
}
I am accessing it like so, but using external functions like showAjaxLoader() just doesn't work! it says this function is undefined:
function registerUser(data) {
ajaxCall(pathServiceRegister, "POST", undefined, JSON.stringify(data), function (result) {
// SOME CODE THAT RUNS WHEN IT'S COMPLETE
// External method:
showAjaxLoader(false); // Doesn't work
});
});
function showAjaxLoader(show) {
var loader = $('.ajax-loader');
if (show) {
loader.fadeIn("fast");
} else {
loader.fadeOut("fast");
}
}
What am I doing wrong?
Thanks :)
Worked out some sample. this may be good practice. Try this :
$(document).ready(function() {
$("button").click(function() {registerUser();});
});
var Scallback = function(arg) {
alert("Success :"+arg);
showAjaxLoader(true);
}
var Ecallback = function(arg) {
alert("Err :"+arg);
showAjaxLoader(true);
}
function showAjaxLoader(show) {
var loader = $('.ajax-loader');
if (show) {
loader.fadeIn("fast");
} else {
loader.fadeOut("fast");
}
}
function ajaxCall(url, type, Scallback, Ecallback) {
$.ajax({
url : url,
type : type,
async : true,
success : function(result) {
Scallback(result);
},
error : function(data) {
Ecallback(data)
}
});
}
function registerUser()
{
ajaxCall(pathServiceRegister, "GET", Scallback, Ecallback);
}
Have you tried to do something like:
var that = this;
function registerUser(data) {
ajaxCall(pathServiceRegister, "POST", undefined, JSON.stringify(data), function (result) {
// SOME CODE THAT RUNS WHEN IT'S COMPLETE
// External method:
that.showAjaxLoader(false);
});
});
Declare your method like this
var obj = {
showAjaxLoader : function(show) {
var loader = $('.ajax-loader');
if (show) {
loader.fadeIn("fast");
} else {
loader.fadeOut("fast");
}
}
}
Then inside ajax, call obj.showAjaxLoader(false); This may work.
I declare two object with name,link and page properties. After receiving data from Twitch API, I add a property status to my objects, which works inside the function, but leaving it I can't access status property anymore. I even tried to set the status property using getApi to return the status as streamer0.status=getApi(); but it does not work either.
var streamer0={name:"freecodecamp"};
streamer0.link='https://api.twitch.tv/kraken/streams/'+streamer0.name; streamer0.page='https://www.twitch.tv/'+streamer0.name;
var streamer1={name:"famasfordemacia"};
streamer1.link='https://api.twitch.tv/kraken/streams/'+streamer1.name;
streamer1.page='https://www.twitch.tv/'+streamer1.name;
var link="";
$(document).ready(function(){
load();
function load(){
for(var i=0;i<2;i++)
{
switch(i){
case 0:{
link=streamer0.link;
getApi(streamer0);
console.log(streamer0.status) //it does not work
break;
}
case 1:{
link=streamer1.link;
getApi(streamer1);
console.log(streamer1.status) //it does not work
break;
}
}
}
function getApi(x){
$.ajax({
type: 'GET',
url: link,
headers: {
'Client-ID': 'xxxxxxxxxxxxx'
},
success: function(data) {
if(data["stream"]==null)
{
x.status="offline";
console.log(x.status)//works
}
else
{
x.status="online";
}
}
});
}
});
You are Using Ajax , its asynchronous , so you have three options :
1 - put all you code inside the success callback which will be a big miss.
function getApi(x) {
$.ajax({
type: 'GET',
url: link,
headers: {
'Client-ID': 'xxxxxxxxxxxxx'
},
success: function (data) {
// ALL YOUR CODE IN HERE
}
});
}
2 - Using a callback function :
function getApi(x, callback) {
$.ajax({
type: 'GET',
url: link,
headers: {
'Client-ID': 'xxxxxxxxxxxxx'
},
success: function (data) {
// PASS YOUR DATA YOU THE CALL BACK
callback(data);
}
});
}
// THEN USE IT IN THE LOAD FUNCTION AS THE FOLLOWING
function load(){
for(var i=0;i<2;i++)
{
switch(i){
case 0:{
link=streamer0.link;
getApi(streamer0,function(data){
console.log(data.status) //it does not work
});
break;
}
case 1:{
link=streamer1.link;
getApi(streamer1,function(data){
console.log(data.status) //it does not work
});
break;
}
}
}
3 - is using Promise (https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise).
It is a asynchronous call so you need wait until the call is done,
function getApi(x) {
return $.ajax({
type: 'GET',
url: link,
headers: {
'Client-ID': 'xxxxxxxxxxxxx' }});
case 0:{
link=streamer0.link;
getApi(streamer0).success(function(data){
if(data["stream"]==null)
{
streamer0.status="offline";
console.log(streamer0.status)//works
}
else
{
streamer0.status="online";
}
}
console.log(streamer0.status) //it does not work
});
break;
}
hope It helps you, :)
I need to combine three methods:
An AJAX to check the existence of a code
If the code exists, confirm whether to overwrite
Overwrite
I've written three methods that return a $.Deferred in order to chain them together with .done(), which are below:
function checkFunction() {
var code = $("#code").val();
return $.ajax({
url: "${pageContext.request.contextPath}/dataManagement/codeMaintenance/check",
method: "POST",
async: false,
data: {
"reasonCode": code
},
success: function(response, textStatus, jqXHR) {
var exists = response.dataMap.exists;
console.log("Code exists: " + exists);
if (exists == true) {
return $.Deferred().resolve(true);
} else {
return $.Deferred().reject();
}
}, error: function() {
return $.Deferred().reject("AJAX ERROR");
}
});
};
var confirmFunction = function(codeExists) {
console.log("Confirming overwrite");
if (codeExists == true) {
var confirm = confirm("Code Exists: Do you wish to overwrite?");
if (confirm == true) {
return $.Deferred(true);
} else {
return $.Deferred(false);
}
} else {
return $.Deferred(true);
}
};
var saveFunction = function() {
console.log("Saving");
var code = $("#code").val();
return $.ajax({
url: "${pageContext.request.contextPath}/dataManagement/codeMaintenance/save",
method: "POST",
data: {
"reasonCode": code
},
success: function(response, textStatus, jqXHR) {
alert("test");
return $.Deferred(true);
}
});
};
I then attempt to execute via this line:
checkFunction().done(confirmFunction(codeExists)).done(saveFunction());
Unfortunately, the parameter I set on the $.Deferred from the first method does not get passed as a parameter to confirmFunction().
What am I doing wrong?
Jason
In short: plenty.
You try to use return inside of asynchronous functions in the success handlers of your $.ajax() calls.
Here you pass the result of the function call and not a reference of the function as callbacks:
checkFunction().done(confirmFunction(codeExists)).done(saveFunction());
This should be more like this:
checkFunction().done(confirmFunction).done(saveFunction);
In confirmFunction() you return a new Deferred object. What you should do is create a Deferred object, return the respective promise and then resolve/reject the Deferred object. So, e.g., your checkFunction() function should look like this:
function checkFunction() {
var code = $("#code").val();
// create deferred object
var result = $.Deferred();
return $.ajax({
url: "${pageContext.request.contextPath}/dataManagement/codeMaintenance/check",
method: "POST",
async: false,
data: {
"reasonCode": code
},
success: function(response, textStatus, jqXHR) {
var exists = response.dataMap.exists;
console.log("Code exists: " + exists);
if (exists == true) {
result.resolve(true);
} else {
result.reject();
}
}, error: function() {
result.reject("AJAX ERROR");
}
});
return result.promise();
}